package com.alibaba.citrus.ots.forecast.facade.service;

import com.alibaba.citrus.ots.common.annotation.EpochTransactional;
import com.alibaba.citrus.ots.common.annotation.FacadeInvoker;
import com.alibaba.citrus.ots.common.exception.FacadeException;
import com.alibaba.citrus.ots.common.exception.FunctionException;
import com.alibaba.citrus.ots.common.lock.RedisLock;
import com.alibaba.citrus.ots.common.log.ModuleEnum;
import com.alibaba.citrus.ots.common.model.ApiContext;
import com.alibaba.citrus.ots.common.util.CalendarCompareUtil;
import com.alibaba.citrus.ots.forecast.common.DateUtils;
import com.alibaba.citrus.ots.forecast.common.LogUtils;
import com.alibaba.citrus.ots.forecast.functions.forecastorder.ability.ForecastOrderLineAbility;
import com.alibaba.citrus.ots.forecast.functions.forecastorder.ability.PriceQueryUtils;
import com.alibaba.citrus.ots.forecast.functions.forecastorder.ability.ScanQueue;
import com.alibaba.citrus.ots.forecast.functions.forecastorder.ability.StrategyCalculate;
import com.alibaba.citrus.ots.forecast.functions.forecastorder.constants.ForecastConstants;
import com.alibaba.citrus.ots.forecast.functions.forecastorder.entity.ForecastOrderEntity;
import com.alibaba.citrus.ots.forecast.functions.forecastorder.entity.ForecastOrderLineEntity;
import com.alibaba.citrus.ots.forecast.functions.forecastorder.factory.ForecastOrderFactory;
import com.alibaba.citrus.ots.forecast.functions.forecastorder.factory.ForecastOrderLineFactory;
import com.alibaba.citrus.ots.forecast.repository.*;
import com.alibaba.cz.base.tool.Nullable;
import com.alibaba.cz.base.tool.UUIDUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.log.model.OpLogModel;
import com.alibaba.cz.base.tool.log.model.OperatorType;
import com.alibaba.cz.base.tool.message.ErrorMessage;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.db.service.CustomSequenceAccessor;
import com.alibaba.lattice2.epoch.middleware.mq.runtime.EpochMessageService;
import com.alibaba.lattice2.epoch.sdk.model.Result;
import com.alibaba.lattice2.epoch.user.dto.LoginUser;
import com.alibaba.lattice2.epoch.user.service.EpochLoginUserService;
import com.epoch.app.bcots.contants.BcOtsConstants;
import com.epoch.app.bcots.model.dto.ScItemSDO;
import com.epoch.app.bcots.model.dto.*;
import com.epoch.app.bcots.platform_enhance.SaleOrderTag;
import com.epoch.app.bcots.service.BaseDataService;
import com.epoch.app.bcots.service.BcOtsService;
import com.epoch.app.bcots.service.UnifiedInventoryService;
import com.epoch.app.otsb2btradecenter.api.orderwrite.service.OrderWriteService;
import com.epoch.app.otsb2btradecenter.dto.request.SaveSaleOrderRequest;
import com.epoch.app.otsb2btradecenter.dto.response.BatchCreateOrderResponse;
import com.epoch.app.otsb2btradecenter.model.dto.TradeMessageSDO;
import com.epoch.app.otsb2btradecenter.sdo.OrderLineSDO;
import com.epoch.app.otsb2btradecenter.sdo.OrderSDO;
import com.epoch.app.otsforecastsales.api.forecastorderlinequery.dto.CountRefuseLineRequest;
import com.epoch.app.otsforecastsales.api.forecastorderlinequery.dto.CountRefuseLineResponse;
import com.epoch.app.otsforecastsales.api.forecastorderlinequery.service.ForecastOrderLineQueryService;
import com.epoch.app.otsforecastsales.api.forecastorderwrite.dto.AnalysisDealMsgHandleRequest;
import com.epoch.app.otsforecastsales.api.forecastorderwrite.dto.CreateForecastOrderExportRequest;
import com.epoch.app.otsforecastsales.api.forecastorderwrite.dto.DeleteActivityForecastRequest;
import com.epoch.app.otsforecastsales.api.forecastorderwrite.dto.ForecastOrderStatusBackRequest;
import com.epoch.app.otsforecastsales.api.forecastorderwrite.service.ForecastOrderWriteService;
import com.epoch.app.otsforecastsales.domian.forecastorderline.dto.UpdateCollectStatusRequest;
import com.epoch.app.otsforecastsales.dto.request.CancelForecastOrderRequest;
import com.epoch.app.otsforecastsales.dto.request.ForecastOrderExportRequest;
import com.epoch.app.otsforecastsales.dto.request.*;
import com.epoch.app.otsforecastsales.dto.response.CancelForecastOrderReponse;
import com.epoch.app.otsforecastsales.dto.response.ConfirmForecastResponse;
import com.epoch.app.otsforecastsales.dto.response.CreateForecastOrderReponse;
import com.epoch.app.otsforecastsales.dto.response.ModifyForecastOrderReponse;
import com.epoch.app.otsforecastsales.enums.ForecastStatusEnum;
import com.epoch.app.otsforecastsales.failorder.service.FailOrderService;
import com.epoch.app.otsforecastsales.model.dto.*;
import com.epoch.app.otsforecastsales.model.enums.ForecastDealStatusSEO;
import com.epoch.app.otsforecastsales.model.enums.ForecastDealTypeSEO;
import com.epoch.app.otsforecastsales.model.enums.ForecastOrderLogEnum;
import com.epoch.app.otsforecastsales.sdo.ForecastOrderLineSDO;
import com.epoch.app.otsforecastsales.sdo.ForecastOrderSDO;
import com.epoch.app.otsforecastsales.sdo.MainOrderInfo;
import com.epoch.app.otsforecastsales.service.OtsForecastSalesService;
import com.epoch.app.otsplatformenhance.api.customeraddressquery.service.CustomerAddressQueryService;
import com.epoch.app.otsplatformenhance.api.customerquery.service.CustomerQueryService;
import com.epoch.app.otsplatformenhance.api.group.scitemgroupquery.service.ScItemGroupQueryService;
import com.epoch.app.otsplatformenhance.api.organizationquery.service.OrganizationQueryService;
import com.epoch.app.otsplatformenhance.api.scitemquery.service.ScItemQueryService;
import com.epoch.app.otsplatformenhance.api.strategyquery.service.StrategyQueryService;
import com.epoch.app.otsplatformenhance.channel.service.ChannelService;
import com.epoch.app.otsplatformenhance.dictionaryquery.service.DictionaryQueryService;
import com.epoch.app.otsplatformenhance.domain.scitemunit.dto.ScItemUnitLoadListRequest;
import com.epoch.app.otsplatformenhance.domain.scitemunit.model.ScItemUnit;
import com.epoch.app.otsplatformenhance.domain.scitemunit.service.ScItemUnitService;
import com.epoch.app.otsplatformenhance.dto.request.CustomerAddressBatchRequest;
import com.epoch.app.otsplatformenhance.dto.request.CustomerAddressRequest;
import com.epoch.app.otsplatformenhance.dto.request.CustomerRequest;
import com.epoch.app.otsplatformenhance.dto.request.QueryScItemGroupRequest;
import com.epoch.app.otsplatformenhance.dto.response.ScItemGroupResponse;
import com.epoch.app.otsplatformenhance.enums.OrganizationTypeEnum;
import com.epoch.app.otsplatformenhance.enums.StrategyTypeEnum;
import com.epoch.app.otsplatformenhance.inventoryallotquery.service.InventoryAllotQueryService;
import com.epoch.app.otsplatformenhance.model.dto.*;
import com.epoch.app.otsplatformenhance.model.enums.RuleTypeEnum;
import com.epoch.app.otsplatformenhance.sdo.CustomerAddressSDO;
import com.epoch.app.otsplatformenhance.sdo.OrganizationSDO;
import com.epoch.app.otsplatformenhance.sdo.*;
import com.epoch.app.otsplatformenhance.service.OtsPlatformEnhanceService;
import com.epoch.app.otspricecenter.api.activityquery.service.ActivityQueryService;
import com.epoch.app.otspricecenter.dto.request.ActivityInfoRequest;
import com.epoch.app.otspricecenter.dto.request.ActivityItemInfoRequest;
import com.epoch.app.otspricecenter.dto.response.ActivityInfoResponse;
import com.epoch.app.otspricecenter.model.dto.ActivityResponse;
import com.epoch.app.otspricecenter.model.dto.QueryActivityRequest;
import com.epoch.app.otsunifiedinventory.api.allocaterelationread.dto.QueryAllocateRelationForOrderRequest;
import com.epoch.app.otsunifiedinventory.api.allocaterelationread.service.AllocateRelationReadService;
import com.epoch.app.otsunifiedinventory.sdo.AllocateRelationSDO;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Primary;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Future;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;


@Service
@Primary
public class ForecastOrderWriteServiceImpl implements ForecastOrderWriteService {
    public static final String ANALYZE_BATCH_NO = "analysisBatchNo";
    public static final String ANALYZE_TYPE = "type";
    public static final String ANALYZE_USER_NO = "analysisUserNo";
    public static final String ANALYZE_ORDER_LINE_IDS = "ids";
    public static final String ANALYZE_API_CONTEXT = "apiContext";
    public static final String ANALYZE_MESSAGE_CODE = "forecast_order_analysis_message";
    public static final String ANALYZE_MESSAGE_TOPIC = "CR_FORECAST_ANALYSIS";
    public static final String ANALYZE_MESSAGE_TAG = "forecastAnalysis";
    //前端页面传入参数，与前端协商确定
    public static final String AUTO_CREATE_SALE_ORDER_FLAG = "joinAndHandle";
    @Resource
    ForecastOrderLineAbility forecastOrderLineAbility;
    @Resource
    private ForecastOrderWriteRepository forecastOrderWriteRepository;
    @Resource
    private ForecastOrderQueryRepository forecastOrderQueryRepository;
    @Resource
    private ForecastOrderLineQueryService forecastOrderLineQueryService;
    @Resource
    ForecastOrderLineWriteRepository forecastOrderLineWriteRepository;
    @Resource
    ForecastOrderLineQueryRepository forecastOrderLineQueryRepository;
    @Resource
    DealLineQueryRepository dealLineQueryRepository;
    @Resource
    DealLineWriteRepository dealLineWriteRepository;
    @Resource
    CustomerAddressQueryService customerAddressQueryService;
    @Resource
    ScItemQueryService scItemQueryService;
    @Resource
    ScanQueue scanQueue;
    @Resource
    StrategyCalculate StrategyCalculate;
    @Autowired
    ScItemGroupQueryService scItemGroupQueryService;
    @Autowired
    CustomerQueryService customerQueryService;
    @Autowired
    OrganizationQueryService organizationQueryService;
    @Autowired
    ChannelService channelService;
    @Autowired
    CustomSequenceAccessor customSequenceAccessor;
    @Resource
    BaseDataService baseDataService;
    @Resource
    UnifiedInventoryService unifiedInventoryService;
    @Resource
    DictionaryQueryService dictionaryQueryService;
    @Resource
    ActivityQueryService activityQueryService;
    @Resource
    ScItemUnitService scItemUnitService;
    @Resource
    OrderWriteService orderWriteService;
    @Resource
    FailOrderService failOrderService;
    @Resource
    private InventoryAllotQueryService inventoryAllotQueryService;
    @Resource
    private StrategyQueryService strategyQueryService;

    @Resource(name = "scItemsQueryTaskExecutor")
    private ThreadPoolTaskExecutor scItemsQueryTaskExecutor;
    @Resource(name = "forecastSaleTaskExecutor")
    private ThreadPoolTaskExecutor forecastSaleTaskExecutor;

    @Resource
    private PriceQueryUtils priceQueryUtils;
    @Resource
    private EpochMessageService messageService;
    @Resource
    private OtsForecastSalesService otsForecastSalesService;

    @Resource
    private OtsPlatformEnhanceService otsPlatformEnhanceService;
    @Resource
    private AllocateRelationReadService allocateRelationReadService;
    @Resource
    private BcOtsService bcOtsService;
    @Resource
    private EpochLoginUserService epochLoginUserService;

    @Resource
    private ApplicationContext applicationContext;


    private static final Log log = Log.getLogger(ForecastOrderWriteServiceImpl.class);

    /*
    创建预报订单草稿 王成
     */
    @Override
    @FacadeInvoker
    @EpochTransactional(appCode = "ots_forecast_sales", dataSourceCode = "cr_ots")
    public Result<CreateForecastOrderReponse> createForecastOrder(CreateForecastOrderRequest createForecastOrderRequest) {
        log.info("预报订单创建或修改入参 = {}", JSONObject.toJSONString(createForecastOrderRequest));
        // 构造返回值 返回结果封装
        CreateForecastOrderReponse saveForecastOrderReponse = new CreateForecastOrderReponse();
        ArrayList<String> orderIdList = new ArrayList<>();
        //  工程构造entity
        List<ForecastOrderEntity> forecastOrderList = ForecastOrderFactory.createDraft(createForecastOrderRequest);
        // 保存预报订单
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderList) {
            String id = forecastOrderEntity.save();
            orderIdList.add(id);
        }
        saveForecastOrderReponse.setOrderIds(orderIdList);
        return Result.success(saveForecastOrderReponse);
    }

    /*
        更改预报单保存草稿 王成
     */
    @Override
    @FacadeInvoker
    public Result<ModifyForecastOrderReponse> modifyForecastOrder(ModifyForecastOrderRequest modifyForecastOrderRequest) {
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        log.info("预报订单修改入参= {}", JSONObject.toJSONString(modifyForecastOrderRequest));
        //list入参怎么办
        Integer count = 0;
        // 构造返回值 返回结果封装
        ModifyForecastOrderReponse modifyForecastOrderReponse = new ModifyForecastOrderReponse();
        //  工程构造entity
        List<ForecastOrderEntity> forecastOrderList = ForecastOrderFactory.modifyDraft(modifyForecastOrderRequest);
        // 保存预报订单
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderList) {
            Integer count1 = forecastOrderEntity.modify();
            LogUtils.printOperateLog(forecastOrderEntity.getForecastOrderSDO().getId(), ForecastOrderLogEnum.EDIT.getForecastOrderLogValue(), "编辑预报订单", loginUser);
            count += count1;
        }
        modifyForecastOrderReponse.setCount(count);
        return Result.success(modifyForecastOrderReponse);
    }

    /*
        取消 预报单保存草稿 王成
     */
    @Override
    @FacadeInvoker
    public Result<CancelForecastOrderReponse> cancelForecastOrder(CancelForecastOrderRequest cancelForecastOrderRequest) {
        List<ForecastOrderSDO> waitReplyList=new ArrayList<>();
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        log.info("预报订单取消入参 = {}", JSONObject.toJSONString(cancelForecastOrderRequest));
        // 构造返回值 返回结果封装
        CancelForecastOrderReponse cancelForecastOrderReponse = new CancelForecastOrderReponse();
        // 获取主键集合
        List<String> ids = cancelForecastOrderRequest.getIds();
        if (CollectionUtils.isEmpty(ids)) {
            return Result.fail(cancelForecastOrderReponse, "error", "id集合不能为空");
        }
        //查询订单是否存在
        List<ForecastOrderSDO> forecastOrderSDOList = forecastOrderQueryRepository.batchQueryForecastOrder(ids);
        if (CollectionUtils.isEmpty(forecastOrderSDOList)) {
            return Result.fail(cancelForecastOrderReponse, "error", "订单不存在");
        }
        //判断订单状态是部分回复、草稿和待提交可以取消
        for (ForecastOrderSDO forecastOrderSDO : forecastOrderSDOList) {
            Integer status = forecastOrderSDO.getStatus();
            if (ForecastStatusEnum.of(status).equals(ForecastStatusEnum.PARTIAL_REPLY) || ForecastStatusEnum.of(status).equals(ForecastStatusEnum.COMPLETED) || ForecastStatusEnum.of(status).equals(ForecastStatusEnum.CANCELLED)) {
                return Result.fail(cancelForecastOrderReponse, "error", "订单部分回复、已完成或已取消状态，不可取消");
            }
            //待回复状态需要判断有效性拦截策略，命中拦截不能取消
            if (ForecastStatusEnum.of(status).equals(ForecastStatusEnum.WAITING_FOR_REPLY)) {
                waitReplyList.add(forecastOrderSDO);
            }
        }

        //待回复状态的保存需要效验有效性策略 20220405需求 待回复状态取消(add by myw) 只有业务员角色才效验待回复状态的有效性检查
        //判断待回复状态的订单是否可以取消
        //根据查询结果 判断是时间段还是截止时间 是拦截还是提示
        //如果是拦截的话不允许取消  提示的话可以取消
        checkValidity(waitReplyList);

        // 批量改变状态
        Integer count = forecastOrderWriteRepository.batchModify(ids);
        for (String id : ids) {
            LogUtils.printOperateLog(id, ForecastOrderLogEnum.EDIT.getForecastOrderLogValue(), "取消预报订单", loginUser);

            //add by 皓晖 at 20211217 for 发送取消预报订单消息 begin
            this.cancelSendMsg(id);
            //add by 皓晖 at 20211217 for 发送取消预报订单消息 end
        }
//        if (!Objects.nonNull(cancelForecastOrderReponse)) {
//            log.error("ForecastOrderWriteServiceImpl#cancelForecastOrder_fail");
//        }
        cancelForecastOrderReponse.setCount(count);
        return Result.success(cancelForecastOrderReponse);
    }

    private void checkValidity(List<ForecastOrderSDO> waitReplyList) {
        EmployeeGetCurrentLoginResponse currentLoginResponse = bcOtsService.employeeGetCurrentLogin();
        if (CollectionUtils.isNotEmpty(waitReplyList)&&currentLoginResponse.getOnlySales()) {

            for (ForecastOrderSDO forecastOrderSDO : waitReplyList) {
                    MoreConditionQueryRequest moreConditionQueryRequest = new MoreConditionQueryRequest();
                    moreConditionQueryRequest.setStrategyType(StrategyTypeEnum.VALIDITY.getCode());
                    moreConditionQueryRequest.setOrganizationCode(forecastOrderSDO.getOrganizationCode());//forecastOrderSDO.getOrganizationCode()
                    moreConditionQueryRequest.setChannelCode(forecastOrderSDO.getChannelCode());//forecastOrderSDO.getChannelCode()
                    moreConditionQueryRequest.setWareHouseCode(forecastOrderSDO.getWareHouseCode());
                    log.info("ForecastOrderEntity|save|"+forecastOrderSDO.getOrderBizId()+"|查询有效期校验|request|", JSONObject.toJSONString(moreConditionQueryRequest));
                    Result<MoreConditionQueryResponse> moreConditionQueryResponseResult = strategyQueryService.moreConditionQuery(moreConditionQueryRequest);
                    log.info("ForecastOrderEntity|save|"+forecastOrderSDO.getOrderBizId()+"|查询有效期校验|result|", JSONObject.toJSONString(moreConditionQueryResponseResult));
                    MoreConditionQueryResponse moreConditionQueryResponse = moreConditionQueryResponseResult.getResult();

                    if (Objects.nonNull(moreConditionQueryResponse)) {
                        StrategySDO strategySDO = moreConditionQueryResponse.getStrategySDO();
                        List<DimensionSDO> dimensionSDOList = strategySDO.getDimensionSDOList();
                        DimensionSDO dimensionSDO = dimensionSDOList.get(0);
                        //获取规则
                        String value = dimensionSDO.getRuleName();
                        if (StringUtils.equals(RuleTypeEnum.TIME_POINT.getCode(), value)) {
                            //获取规则值
                            String ruleValue = dimensionSDO.getRuleValue();
                            //判断截止时间是否满足 当前时间大于截止时间 不满足
                            boolean compare = CalendarCompareUtil.compareDateTimes(null, ruleValue);
                            if (compare) {
                                Boolean executeAction = dimensionSDO.getExecuteAction();
                                if (executeAction) {
                                    throw new FunctionException("OTS-04-001-00-15-048","该时间范围内不允许修改，请联系订单员修改");
                                    // return "该时间范围内不允许修改，请联系订单员修改";
                                }
                            }
                        }
                        if (StringUtils.equals(RuleTypeEnum.TIME_FRAME.getCode(), value)) {
                            String ruleValue = dimensionSDO.getRuleValue();
                            String substring = ruleValue.substring(ruleValue.indexOf("[") + 1, ruleValue.indexOf("]") ).replace("\"", "");
                            String[] split = substring.split(",");

                            String ruleValueSplit = split[0];
                            String ruleValueSplit1 = split[1];
                            boolean compareDateTimes = CalendarCompareUtil.compareDateTimes(ruleValueSplit, ruleValueSplit1);
                            //如果为true满足可以取消
                            if (!compareDateTimes) {
                                Boolean executeAction = dimensionSDO.getExecuteAction();
                                if (executeAction) {
                                    throw new FunctionException("OTS-04-001-00-15-048","该时间范围内不允许修改，请联系订单员修改");
                                    // return "该时间范围内不允许修改，请联系订单员修改";
                                }
                            }
                        }
                    }
                }

        }
    }

    /**
     * 取消预报订单-发送消息
     */
    private void cancelSendMsg(String id) {
        ForecastOrderLineSDO queryParam = new ForecastOrderLineSDO();
        queryParam.setMainOrderId(id);
        List<ForecastOrderLineSDO> orderLineSDOS = this.forecastOrderLineQueryRepository.queyrLineDetailList(queryParam);
        if (orderLineSDOS != null) {
            for (ForecastOrderLineSDO paramLineSDO : orderLineSDOS) {
                this.sendMessage("ForecastCancled", paramLineSDO);
                paramLineSDO.setStatus(ForecastStatusEnum.CANCELLED.getNumValue());
                forecastOrderLineWriteRepository.update(paramLineSDO);
            }
        }
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> submitForecast(SubmitForecastRequest submitForecastRequest) {
        log.info("预报订单提交入参 = {}", JSONObject.toJSONString(submitForecastRequest));
        if (CollectionUtils.isEmpty(submitForecastRequest.getForecastOrderSDOList())) {
            throw new FacadeException("OTS-04-001-00-15-013");
        }

        List<ForecastOrderSDO> forecastOrderSDOList = submitForecastRequest.getForecastOrderSDOList();
        for (ForecastOrderSDO forecastOrderSDO : forecastOrderSDOList) {
            //获取主单Id
            String orderId = forecastOrderSDO.getId();
            if (StringUtils.isNotEmpty(orderId)) {
                //调用load方法查询 预报订单数据
                ForecastOrderEntity forecastOrderEntity = ForecastOrderFactory.loadById(orderId);
                return forecastOrderEntity.submit(JSONObject.parseObject(JSONObject.toJSONString(submitForecastRequest.getApiContext()), ApiContext.class));
            }
        }
        log.error("ForecastOrderWriteServiceImpl#submitForecast_fail");
        return Result.success(false);
    }

    /**
     * 预报分析，加入分析队列
     *
     * @param batchAnalysisOrdersRequest 用户
     * @return
     */
    /*
    @Override
    @FacadeInvoker
    // todo 自定义aop和事务优先级
//    @EpochTransactional(appCode = "ots_forecast_sales", dataSourceCode = "cr_ots")
    public Result<Boolean> batchAnalysisOrders(BatchAnalysisOrdersRequest batchAnalysisOrdersRequest) {
        if (Objects.isNull(batchAnalysisOrdersRequest)) {
            return Result.fail("SYS_ERR_INVALID_PARAM", "系统错误，参数异常！");
        }
        log.info("预报批量分析入参 = {}", JSONObject.toJSONString(batchAnalysisOrdersRequest));

        //构造数据
        List<ForecastOrderLineEntity> forecastOrderLineEntities;
        forecastOrderLineEntities = ForecastOrderLineFactory.loadOrderLineListByIdsAndSetStatusToAnalyzing(batchAnalysisOrdersRequest);
        if (Objects.isNull(forecastOrderLineEntities)) {
            return Result.fail("SYS_ERR_FOUND_NO_ORDER_LINE", "系统错误，从库中加载订单为空！");
        }
        // 将所有需要分析的订单状态置为1：分析中
//        Boolean updateFlag = ForecastOrderLineEntity.setOrderLineStatusToAnalyzing(forecastOrderLineEntities);
//        if (!updateFlag) {
//            return Result.fail("SYS_ERR_SET_ORDER_LINE_STATUS_FAILED", "系统错误，保存订单行状态失败！");
//        }
        try {
            String batchNo = String.valueOf(System.nanoTime());
            boolean result = setBatchAnalyzeStatusToAnalyzing(forecastOrderLineEntities,batchNo);
            if (!result){
                return Result.fail("SYS_ERR_SAVE_STATUS_FAILED", "系统错误，设置分析状态失败");
            }

            //分析数据设置值
            sendAnalyzeMessage(batchAnalysisOrdersRequest, batchNo);

            return Result.success(result,batchNo);
        } catch (Exception e) {
            log.error("批量分析异常", e);
            e.printStackTrace();
            throw new FunctionException("OTS-04-001-00-15-010");
        }
    }


     */

    /**
     * 将orderline加载放到读取消息过程中，发送消息，只发送orderline id
     */
    @Override
    @FacadeInvoker
    public Result<Boolean> batchAnalysisOrders(BatchAnalysisOrdersRequest batchAnalysisOrdersRequest) {
        if (Objects.isNull(batchAnalysisOrdersRequest)) {
            //data 赋值 false
            return Result.fail(false, "SYS_ERR_INVALID_PARAM", "系统错误，参数异常！");
        }

        if (CollectionUtils.isEmpty(batchAnalysisOrdersRequest.getIds())) {
            return Result.success(true, "分析内容为空!");
        }
        log.info("预报批量分析入参 = {}", JSONObject.toJSONString(batchAnalysisOrdersRequest));

        try {
            String batchNo = String.valueOf(System.nanoTime());
            // 按照批次号和user查询订单列表
            //20220312，解决分析中还可以再次分析问题，将设置分析中操作放到发送消息前，修改为同步
            List<ForecastOrderLineEntity> forecastOrderLineEntities;
            forecastOrderLineEntities = ForecastOrderLineFactory.loadNotAnalyzingOrderLineListByIds(batchAnalysisOrdersRequest);
            if (Objects.isNull(forecastOrderLineEntities)){
                log.error("子单正在分析中");
                return Result.fail(false, "SYS_ERR_ORDERLINE_ANALYZING", "子单正在分析中，请稍后重试！");
            }
            saveBatchAaveavenalyzeStatusToAnalyzing(forecastOrderLineEntities, batchNo);

            boolean result = sendAnalyzeMessage(batchAnalysisOrdersRequest, batchNo);

            return Result.success(result, batchNo);
        } catch (Exception e) {
            log.error("批量分析异常", e);
            throw new FunctionException("OTS-04-001-00-15-010");
        }
    }

    /**
     * 发送分析消息
     * 1、消息内容为待分析的子单id
     *
     * @param batchAnalysisOrdersRequest
     * @param batchNo
     * @return
     */
    private boolean sendAnalyzeMessage(BatchAnalysisOrdersRequest batchAnalysisOrdersRequest, String batchNo) {
        //分析数据设置值
        HashMap<String, Object> message = new HashMap<>();
        message.put(ANALYZE_TYPE, batchAnalysisOrdersRequest.getType());
        message.put(ANALYZE_BATCH_NO, batchNo);
        message.put(ANALYZE_USER_NO, batchAnalysisOrdersRequest.getModifierId());
        message.put(ANALYZE_ORDER_LINE_IDS, batchAnalysisOrdersRequest.getIds());
        message.put(ANALYZE_API_CONTEXT, batchAnalysisOrdersRequest.getApiContext());

        Map<String, String> map = new HashMap<>();
        map.put("_CZ_KEY", BcOtsConstants.TENANT_ID());
        return messageService.sendMessage(ANALYZE_MESSAGE_CODE, ANALYZE_MESSAGE_TOPIC, ANALYZE_MESSAGE_TAG,
                batchNo, JSON.toJSONString(message), map);
    }

    /**
     * 设置分析状态为分析中，子单deal_status及deal_line status都设置为1并保存数据库
     *
     * @param forecastOrderLineEntities 需要设置的子单集合
     * @param batchNo                   批次号
     * @return 成功：true
     * 失败：false
     */
    @EpochTransactional(appCode = "ots_forecast_sales", dataSourceCode = "cr_ots")
    private boolean saveBatchAaveavenalyzeStatusToAnalyzing(List<ForecastOrderLineEntity> forecastOrderLineEntities, String batchNo) {
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        if (CollectionUtils.isEmpty(forecastOrderLineEntities)) {
            return false;
        }
        ForecastOrderLineEntity.setOrderLineStatusToAnalyzing(forecastOrderLineEntities);

        //将数据的信息插入分析队列的表中
        List<DealLineSDO> orderLineListToDeal = Nullable.stream(forecastOrderLineEntities).map(it -> {
            ForecastOrderLineSDO forecastOrderLineSDO = it.getForecastOrderLineSDO();
            DealLineSDO dealLineSDO = new DealLineSDO();
            dealLineSDO.setForecastOrderLineId(forecastOrderLineSDO.getId().toString());
            dealLineSDO.setDealStatus(ForecastDealStatusSEO.ANALYSIS_ING.getStatus());
            dealLineSDO.setDealType(ForecastDealTypeSEO.BATCH_ANALYSIS.getDealTypeCode().toString());
            dealLineSDO.setModifierName(forecastOrderLineSDO.getModifierName());
            dealLineSDO.setModifierId(forecastOrderLineSDO.getModifierId());
            dealLineSDO.setDealTime(new Date());
            dealLineSDO.setStatus(1);
            dealLineSDO.setBatchNumber(batchNo);

            //添加日志
            //LogUtils.printOperateLog(forecastOrderLineSDO.getMainOrderId(), ForecastOrderLogEnum.BATCH_ANALYSIS.getForecastOrderLogValue(), "分析订单",loginUser);
            return dealLineSDO;
        }).collect(Collectors.toList());

        //创建分析队列的表中数据
        dealLineWriteRepository.batchCreate(orderLineListToDeal);
        return true;
    }

    /**
     * 打印操作日志
     *
     * @param forecastOrderLineSDO
     * @param modifierName
     * @param activeValue          激活值
     */
    @Deprecated
    private void printOperateLog(ForecastOrderLineSDO forecastOrderLineSDO, String modifierName, String activeValue, Integer type) {
        OpLogModel.OpLogModelBuilder<String> builder = OpLogModel.builder();
        OpLogModel<String> opLogModel = builder.build();
        opLogModel.setModuleName(ModuleEnum.FORECAST_SALES.getModuleName());
        opLogModel.setModuleId(String.valueOf(ModuleEnum.FORECAST_SALES.getModuleId()));
        //ForecastOrderLogEnum 类型使用的枚举值，解析过程在纪元中
        opLogModel.setOperateType(type);
        opLogModel.setObjectId(forecastOrderLineSDO.getMainOrderId());
        opLogModel.setObjectName("id");
        Map<String, String> map = new HashMap<>();
        map.put("name", modifierName);
        map.put("active", activeValue);
        String logInfo = JSONObject.toJSONString(map);
        opLogModel.setFeatures(logInfo);
        opLogModel.setOperatorId(modifierName);
        opLogModel.setOperatorType(OperatorType.USER.getOperatorType());
        log.asyncMonitorObjectChangeV2(opLogModel);
    }

    /**
     * 预报订单分析消息处理入口
     *
     * @param analysisDealMsgHandleRequest
     * @return
     */
    @Override
    public Result<Void> analysisDealMsgHandle(AnalysisDealMsgHandleRequest analysisDealMsgHandleRequest) {


        if (Objects.isNull(analysisDealMsgHandleRequest)) {
            return Result.fail("SYS_ERR_ANY_INVALID_PARAM", "系统异常，消息内容为空");
        }
        String message = analysisDealMsgHandleRequest.getMessage();

        if (StringUtils.isBlank(message)) {
            return Result.fail("SYS_ERR_ANY_INVALID_MSG", "系统异常，项目内容为空");
        }

        BatchAnalysisOrdersRequest pageQueryForecastRequest = new BatchAnalysisOrdersRequest();

        String type = "";
        List<String> ids = new ArrayList<>();
        ApiContext apiContext = null;
        try {
            JSONObject jsonObject = JSONObject.parseObject(message);
            // 消息转换
            // 通过消息获取
            String batchNumber = jsonObject.getString(ANALYZE_BATCH_NO);
            type = jsonObject.getString(ANALYZE_TYPE);
            ids = jsonObject.getJSONArray(ANALYZE_ORDER_LINE_IDS).toJavaList(String.class);
            apiContext = jsonObject.getObject(ANALYZE_API_CONTEXT, ApiContext.class);
            pageQueryForecastRequest.setIds(ids);

            log.info("analysisDeal Step -1 start analysisDeal#new logic, batch no:{}", batchNumber);

            // 按照批次号和user查询订单列表
            List<ForecastOrderLineEntity> forecastOrderLineEntities;
            forecastOrderLineEntities = ForecastOrderLineFactory.loadOrderLinesByIds(pageQueryForecastRequest);
            List<ForecastOrderLineSDO> batchAnalysisOrdersRequest;
            if (CollectionUtils.isNotEmpty(forecastOrderLineEntities)) {
                batchAnalysisOrdersRequest = Nullable.stream(forecastOrderLineEntities).map(it -> it.getForecastOrderLineSDO()).collect(Collectors.toList());

                //设置状态
                //20220312，解决分析中还可以再次分析问题，将设置分析中操作放到发送消息前，修改为同步
                //forecastOrderLineAbility.setBatchAnalyzeStatusToAnalyzing(forecastOrderLineEntities, batchNumber);
                scanQueue.analyzeOrderLineList(batchNumber, batchAnalysisOrdersRequest);
            }
        } catch (Exception e) {
            log.error("Parse message failed:" + e.getMessage(), e);
        }

        // 根据type决定是否走确认逻辑
        if (AUTO_CREATE_SALE_ORDER_FLAG.equalsIgnoreCase(type)) {
            try {
                BatchSaveOrderConfirmRequest batchSaveOrderConfirmRequest = new BatchSaveOrderConfirmRequest();
                batchSaveOrderConfirmRequest.setIds(ids);
                batchSaveOrderConfirmRequest.setApiContext(apiContext);
                otsForecastSalesService.batchSaveOrderConfirm(batchSaveOrderConfirmRequest);
            } catch (Exception e) {
                log.error("analysisDeal submit failed:" + e.getMessage(), e);
            }
        }

        log.info("analysisDeal Step 999 end, analysisDeal#new logic");
        return Result.success(null);
    }

    /**
     * 批量修改
     *
     * @param updateForecastQtyRequest
     * @return
     */
    @Override
    @FacadeInvoker
    @EpochTransactional(appCode = "ots_forecast_sales", dataSourceCode = "cr_ots")
    public Result<Boolean> batchUpdateReplyQuantity(UpdateForecastQtyRequest updateForecastQtyRequest) {
        log.info("预报修改回复数量入参 = {}", JSONObject.toJSONString(updateForecastQtyRequest));
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        if (CollectionUtils.isEmpty(updateForecastQtyRequest.getForecastOrderLineSDOList())) {
            return null;
        } else {
            RefuseForecastRequest refuseForecastRequest = new RefuseForecastRequest();
            List<RefuseForecastDetailRequest> refuseForecastDetailRequests = new ArrayList<>();
            updateForecastQtyRequest.getForecastOrderLineSDOList().stream().forEach(i -> {
                //走拒绝逻辑
                if (StringUtils.isNotEmpty(i.getRefuseReasonCode())) {
                    RefuseForecastDetailRequest refuseForecastDetailRequest = new RefuseForecastDetailRequest();
                    refuseForecastDetailRequest.setId(String.valueOf(i.getId()));
                    refuseForecastDetailRequest.setRefuseReasonCode(i.getRefuseReasonCode());
                    refuseForecastDetailRequests.add(refuseForecastDetailRequest);
                }
            });
            refuseForecastRequest.setRefuseForecastDetailRequests(refuseForecastDetailRequests);
            if (Objects.nonNull(refuseForecastRequest) && CollectionUtils.isNotEmpty(refuseForecastDetailRequests)) {
                batchRefuseForecast(refuseForecastRequest);
            }

        }
        List<ForecastOrderLineSDO> ForecastOrderLineSDONew = updateForecastQtyRequest.getForecastOrderLineSDOList().stream().filter(i -> StringUtils.isEmpty(i.getRefuseReasonCode())).collect(Collectors.toList());
        if (CollectionUtils.isEmpty(ForecastOrderLineSDONew)) {
            return Result.success(true);
        }
        boolean b = forecastOrderLineAbility.updateReplyQuantity(ForecastOrderLineSDONew);
        List<String> collect = Nullable.stream(ForecastOrderLineSDONew).map(it -> {
            return it.getId().toString();
        }).collect(Collectors.toList());
        ForecastOrderActivityRequest forecastOrderActivityRequest = ForecastOrderActivityRequest.builder().ids(collect).build();
        try {
            applicationContext.getBean(ForecastOrderWriteServiceImpl.class).batchActivityCheckForecast(forecastOrderActivityRequest);
        } catch (Exception e) {
            log.error("ForecastOrderWriteServiceImpl#batchUpdateReplyQuantity_fail");
            log.error("预报订单活动检查出错", e);
        }

        for (ForecastOrderLineSDO forecastOrderLineSDO : updateForecastQtyRequest.getForecastOrderLineSDOList()) {
            //添加日志
            LogUtils.printOperateLog(forecastOrderLineSDO.getMainOrderId(), ForecastOrderLogEnum.EDIT.getForecastOrderLogValue(), "编辑预报订单", loginUser);
            //printOperateLog(forecastOrderLineSDO, forecastOrderLineSDO.getModifierName(), "编辑预报订单",ForecastOrderLogEnum.EDIT.getForecastOrderLogValue());
        }
        if (!b) {
            log.error("ForecastOrderWriteServiceImpl#batchUpdateReplyQuantity_fail");
        }
        return Result.success(b);
    }

    private void confirmForecastOrderByOne(ConfirmForecastRequest confirmForecastRequest, ForecastOrderEntity forecastOrderEntity) {

        //1、更新子单状态确认中 ，加入队列表
        forecastOrderEntity.confirmUpdateDealForecast(JSONObject.parseObject(JSONObject.toJSONString(confirmForecastRequest.getApiContext()), ApiContext.class));
        //2、确认校验库存和活动
        ConfirmForecastResponse confirmForecastResponse = forecastOrderEntity.confirmCheckForecastNew(confirmForecastRequest);
        ForecastOrderSDO forecastOrder = forecastOrderEntity.getForecastOrderSDO();
        Map<Long, ForecastOrderLineSDO> lineSDOMap = forecastOrder.getForecastOrderLineSDOList().stream().collect(Collectors.toMap(ForecastOrderLineSDO::getId, f -> f));
        log.info("ForecastOrderWriteServiceImpl#confirmForecastOrderByOne checkInventory " + forecastOrder.getOrderBizId() + JSON.toJSONString(confirmForecastResponse));
        Map<String, String> success = confirmForecastResponse.getSuccessOrderLineMap();
        Map<String, String> fail = confirmForecastResponse.getFailOrderLineMap();
        if (MapUtils.isNotEmpty(confirmForecastResponse.getFailOrderLineMap())) {
            confirmForecastResponse.getFailOrderLineMap().forEach((k, v) -> {
                forecastOrderEntity.backForecastUpdate(lineSDOMap.get(Long.valueOf(k)), fail.get(k));
            });
            forecastOrder.getForecastOrderLineSDOList().forEach(forecast -> {
                String msg = "";
                if (!fail.containsKey(forecast.getId().toString())) {
                    if (MapUtils.isNotEmpty(success)) {
                        msg = success.get(forecast.getId().toString());
                    }
                    forecastOrderEntity.backForecastUpdate(forecast, msg);
                }
            });
            log.error("ForecastOrderWriteServiceImpl#confirmForecastOrderByOne_fail " + forecastOrder.getOrderBizId());
            throw new FunctionException("OTS-04-001-00-15-027", forecastOrder.getOrderBizId() + "|" + confirmForecastResponse.getMessage());
        }
        log.error("666-拆单前--forecastOrderEntity:{}", forecastOrderEntity);
        List<ForecastOrderEntity> forecastOrderEntitiesBuild = ForecastOrderFactory.batchCreateForecastOrder(forecastOrderEntity);
//                String sequenceNo = cretateOrderParamRequest.getSequenceNo();
        log.error("666-拆单后--forecastOrderEntitiesBuild:{}", forecastOrderEntitiesBuild);

        List<OrderSDO> orderSDOS = ForecastOrderFactory.batchCreateOrder(forecastOrderEntitiesBuild, confirmForecastRequest);
        log.error("666-销售单生成--forecastOrderEntitiesBuild:{}", forecastOrderEntitiesBuild);

        SaveSaleOrderRequest saveSaleOrderRequest = new SaveSaleOrderRequest();
        saveSaleOrderRequest.setOrderSDOS(orderSDOS);
        //保存订单
        Result<List<BatchCreateOrderResponse>> response = orderWriteService.saveSaleOrder(saveSaleOrderRequest);
        log.info("BatchCreateOrderResponse 销售订单创建:" + JSON.toJSONString(response));
        if (response != null && CollectionUtils.isEmpty(response.getResult())) {
            throw new FunctionException("OTS-04-001-00-15-037");
        }
        List<BatchCreateOrderRequest> confirmForecastStatuses = new ArrayList<>();
        response.getResult().forEach(batchCreateOrderResponse -> {
            BatchCreateOrderRequest batchCreateOrderRequest = new BatchCreateOrderRequest();
            BeanUtils.copyProperties(batchCreateOrderResponse, batchCreateOrderRequest);
            confirmForecastStatuses.add(batchCreateOrderRequest);
        });
        confirmForecastRequest.setConfirmForecastStatuses(confirmForecastStatuses);
//            log.info();
//            Map<String, String> success = confirmForecastResponse.getSuccessOrderLineMap();
        if (MapUtils.isNotEmpty(success)) {
            success.forEach((k, v) -> {
                forecastOrderEntity.backForecastUpdate(lineSDOMap.get(Long.valueOf(k)), success.get(k));
            });
        }

        this.batchConfirmUpdateForecast(confirmForecastRequest);
//            if (rest == null || rest.getResult() == null || !rest.getResult()) {
//                this.batchConfirmUpdateForecast(confirmForecastRequest);
//            }
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> confirmUpdateDealForecastNew(ConfirmForecastRequest confirmForecastRequest) {
        Result<Boolean> result = batchConfirmUpdateDealForecastV2(confirmForecastRequest);
        //返回对象null值判断
        if (Objects.isNull(result) || !result.getResult() || !result.isSuccess()) {//接口上一步在fail中没有传boolean值，造成fail时npe，应该用isSuccess判断上一步结果
            log.error("ForecastOrderWriteServiceImpl#confirmUpdateDealForecastNew_fail");
        }
        return result;

        /*LoginUser loginUser = epochLoginUserService.getLoginUser();
        log.info("ForecastOrderWriteServiceImpl|confirmUpdateDealForecast|批量确认|参数01 = {}", JSONObject.toJSONString(confirmForecastRequest));
        //根据主订单进行分组
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.confrimForecast(confirmForecastRequest);
        boolean res = true;
        StringBuffer orderIds = new StringBuffer();
        ErrorMessage errorMessage = new ErrorMessage();
        if (CollectionUtils.isNotEmpty(forecastOrderEntities)) {
            for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {

                ForecastOrderSDO forecastOrderSDO = forecastOrderEntity.getForecastOrderSDO();
                List<Long> forecastLineIds = forecastOrderSDO.getForecastOrderLineSDOList().stream().map(ForecastOrderLineSDO::getId).collect(Collectors.toList());
                try {
                    confirmForecastOrderByOne(confirmForecastRequest, forecastOrderEntity);
                } catch (FunctionException e) {
                    FailOrderRequest failOrderRequest = new FailOrderRequest();
                    failOrderRequest.setFailOrderIds(forecastLineIds);
                    failOrderRequest.setApiContext(confirmForecastRequest.getApiContext());
                    failOrderRequest.setSequenceNo(confirmForecastRequest.getSequenceNo());
                    failOrderService.sendFailMsg(failOrderRequest);
                    orderIds.append(forecastOrderSDO.getOrderBizId()).append("|");
                    errorMessage = ErrorMessage.of(e.getError().getErrorCode(), orderIds + e.getError().getErrorMessage());
                    res = false;
                    continue;
                }

                //添加日志
                LogUtils.printOperateLog(forecastOrderEntity.getForecastOrderSDO().getId(), ForecastOrderLogEnum.BATCH_CONFIRM.getForecastOrderLogValue(), "确认预报订单", loginUser);
                //todo  需确认一下添加日志的逻辑，这里是否按主单维度添加即可？
//                for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList()) {
//                    //添加日志
//                    LogUtils.printOperateLog(forecastOrderLineSDO.getMainOrderId(), ForecastOrderLogEnum.BATCH_CONFIRM.getForecastOrderLogValue(), "确认预报订单",loginUser);
//                    //printOperateLog(forecastOrderLineSDO, forecastOrderLineSDO.getModifierName(), "确认预报订单",ForecastOrderLogEnum.BATCH_CONFIRM.getForecastOrderLogValue());
//                }
//                failOrderService.sendFailMsg();
                //创建分析队列的表中数据
            }
            if (!res) {
                return Result.fail(errorMessage.getErrorCode(), errorMessage.getErrorMessage());
            }
        }

        return Result.success(true);*/
    }

    private Result<Boolean> batchConfirmUpdateDealForecastV2(ConfirmForecastRequest confirmForecastRequest) {
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        log.info("ForecastOrderWriteServiceImpl|batchConfirmUpdateDealForecastV2|批量确认|参数01 = {}", JSONObject.toJSONString(confirmForecastRequest));
        //根据主订单进行分组
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.confrimForecast(confirmForecastRequest);
        boolean res = true;
        StringBuffer orderIds = new StringBuffer();
        ErrorMessage errorMessage = new ErrorMessage();
        if (CollectionUtils.isNotEmpty(forecastOrderEntities)) {
            for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
                ForecastOrderSDO forecastOrderSDO = forecastOrderEntity.getForecastOrderSDO();
                List<Long> forecastLineIds = forecastOrderSDO.getForecastOrderLineSDOList().stream().map(ForecastOrderLineSDO::getId).collect(Collectors.toList());
                try (RedisLock lock = new RedisLock("REDIS_CACHE", "batch:" + forecastOrderEntity.getForecastOrderSDO().getId(), 0, 30 * 1000)) {
                    if (!lock.lock()) {
                        errorMessage = ErrorMessage.code("OTS-04-001-00-15-038", orderIds + "该单据正在参与其它操作，请稍后重试");
                        res = false;
                        continue;
                    }
                    confirmForecastOrderByOne(confirmForecastRequest, forecastOrderEntity);
                } catch (FunctionException e) {
                    FailOrderRequest failOrderRequest = new FailOrderRequest();
                    failOrderRequest.setFailOrderIds(forecastLineIds);
                    failOrderRequest.setApiContext(confirmForecastRequest.getApiContext());
                    failOrderRequest.setSequenceNo(confirmForecastRequest.getSequenceNo());
                    failOrderService.sendFailMsg(failOrderRequest);
                    orderIds.append(forecastOrderSDO.getOrderBizId()).append("|");
                    errorMessage = e.getError();
                    res = false;
                    continue;
                } catch (Exception e) {
                    // todo
                    log.error("ForecastOrderWriteServiceImpl#batchConfirmUpdateDealForecastV2_fail");
                    log.error("batchConfirmUpdateDealForecastV2执行异常:", e);
                    continue;
                }

                //添加日志
                LogUtils.printOperateLog(forecastOrderEntity.getForecastOrderSDO().getId(), ForecastOrderLogEnum.BATCH_CONFIRM.getForecastOrderLogValue(), "确认预报订单", loginUser);
                //todo  需确认一下添加日志的逻辑，这里是否按主单维度添加即可？
//                for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList()) {
//                    //添加日志
//                    LogUtils.printOperateLog(forecastOrderLineSDO.getMainOrderId(), ForecastOrderLogEnum.BATCH_CONFIRM.getForecastOrderLogValue(), "确认预报订单",loginUser);
//                    //printOperateLog(forecastOrderLineSDO, forecastOrderLineSDO.getModifierName(), "确认预报订单",ForecastOrderLogEnum.BATCH_CONFIRM.getForecastOrderLogValue());
//                }
//                failOrderService.sendFailMsg();
                //创建分析队列的表中数据
            }
            if (!res) {
                log.error("ForecastOrderWriteServiceImpl#batchConfirmUpdateDealForecastV2_fail");
                // add data content
                return Result.fail(false, errorMessage.getErrorCode(), errorMessage.getDisplayErrorMessage());
            }
        }
        return Result.success(Boolean.TRUE);
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> confirmUpdateDealForecast(ConfirmForecastRequest confirmForecastRequest) {
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        log.info("ForecastOrderWriteServiceImpl|confirmUpdateDealForecast|批量确认|参数01 = {}", JSONObject.toJSONString(confirmForecastRequest));
        //根据主订单进行分组
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.confrimForecast(confirmForecastRequest);
        if (CollectionUtils.isNotEmpty(forecastOrderEntities)) {
            for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
                forecastOrderEntity.confirmUpdateDealForecast(JSONObject.parseObject(JSONObject.toJSONString(confirmForecastRequest.getApiContext()), ApiContext.class));
                for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList()) {
                    //添加日志
                    LogUtils.printOperateLog(forecastOrderLineSDO.getMainOrderId(), ForecastOrderLogEnum.BATCH_CONFIRM.getForecastOrderLogValue(), "确认预报订单", loginUser);
                    //printOperateLog(forecastOrderLineSDO, forecastOrderLineSDO.getModifierName(), "确认预报订单",ForecastOrderLogEnum.BATCH_CONFIRM.getForecastOrderLogValue());
                }

                //创建分析队列的表中数据
            }
        }

        return Result.success(true);
    }

    @Override
    @FacadeInvoker
    @Deprecated
    public Result<List<ConfirmForecastResponse>> batchConfirmCheckForecast(ConfirmForecastRequest confirmForecastRequest) {
        log.info("ForecastOrderWriteServiceImpl|confirmUpdateDealForecast|批量确认|检查入参02 = {}", JSONObject.toJSONString(confirmForecastRequest));
        List<ConfirmForecastResponse> confirmForecastResponses = new ArrayList<>();
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.confrimForecast(confirmForecastRequest);
        ConfirmForecastResponse confirmForecastResponseSuccess = new ConfirmForecastResponse();
        ConfirmForecastResponse confirmForecastResponseFailed = new ConfirmForecastResponse();
        List<String> totalSuccessIds = new ArrayList<>();
        List<String> totalFailedIds = new ArrayList<>();
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
            List<ConfirmForecastResponse> confirmForecastResponseYuan = forecastOrderEntity.confirmCheckForecast(confirmForecastRequest);
            if (CollectionUtils.isNotEmpty(confirmForecastResponseYuan)) {
                boolean existFail = false;
                for (ConfirmForecastResponse confirmForecastResponse : confirmForecastResponseYuan) {
                    //获取成功的子单id
                    //if ("1".equals(confirmForecastResponse.getTag())) {
                    //    List<String> ids = confirmForecastResponse.getIds();
                    //    totalSuccessIds.addAll(ids);
                    //}
                    if (("2".equals(confirmForecastResponse.getTag())
                            || "3".equals(confirmForecastResponse.getTag())) && CollectionUtils.isNotEmpty(confirmForecastResponse.getIds())) {
                        //List<String> ids = confirmForecastResponse.getIds();
                        //totalFailedIds.addAll(ids);
                        existFail = true;
                        break;
                    }
                }
                List<String> ids = forecastOrderEntity.getForecastOrderSDO()
                        .getForecastOrderLineSDOList()
                        .stream()
                        .map(ForecastOrderLineSDO::getId)
                        .map(String::valueOf)
                        .collect(Collectors.toList());
                if (!existFail) {
                    totalSuccessIds.addAll(ids);
                } else {
                    totalFailedIds.addAll(ids);
                }
            }
        }
        confirmForecastResponseSuccess.setIds(totalSuccessIds);
        confirmForecastResponseSuccess.setTag("1");
        confirmForecastResponseFailed.setTag("2");
        confirmForecastResponseFailed.setIds(totalFailedIds);
        confirmForecastResponses.add(confirmForecastResponseSuccess);
        confirmForecastResponses.add(confirmForecastResponseFailed);
        return Result.success(confirmForecastResponses);
    }

    @Override
    @FacadeInvoker
    public Result<ConfirmForecastResponse> batchConfirmCheckForecastNew(ConfirmForecastRequest confirmForecastRequest) {
        log.info("预报确认检查入参02 = {}", JSONObject.toJSONString(confirmForecastRequest));
        ConfirmForecastResponse response = new ConfirmForecastResponse();
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.confrimForecast(confirmForecastRequest);
        Map<String, String> totalSuccessMap = new HashMap<>();
        Map<String, String> totalFailedMap = new HashMap<>();
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
            ConfirmForecastResponse confirmForecastResponseYuan = forecastOrderEntity.confirmCheckForecastNew(confirmForecastRequest);
            List<ForecastOrderLineSDO> forecastOrderLineSDOS = forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList();
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOS) {
                String msg = "";
                if (confirmForecastResponseYuan != null) {
                    response.setMessage(confirmForecastResponseYuan.getMessage());
                    //成功的子单
                    if (MapUtils.isNotEmpty(confirmForecastResponseYuan.getSuccessOrderLineMap())) {
                        Map<String, String> successMap = confirmForecastResponseYuan.getSuccessOrderLineMap();
                        totalSuccessMap.putAll(successMap);
                        if (successMap.containsKey(forecastOrderLineSDO.getId().toString())) {
                            msg = successMap.get(forecastOrderLineSDO.getId().toString());
                        }
                    }
                    //失败的子单
                    if (MapUtils.isNotEmpty(confirmForecastResponseYuan.getFailOrderLineMap())) {
                        Map<String, String> failedMap = confirmForecastResponseYuan.getFailOrderLineMap();
                        totalFailedMap.putAll(failedMap);
                        if (failedMap.containsKey(forecastOrderLineSDO.getId().toString())) {
                            msg = failedMap.get(forecastOrderLineSDO.getId().toString());
                        }
                        //只有失败的情况下走更新状态
                        forecastOrderEntity.backForecastUpdate(forecastOrderLineSDO, msg);
                    }

                }

            }
        }
        response.setSuccessOrderLineMap(totalSuccessMap);
        response.setFailOrderLineMap(totalFailedMap);

        log.info("批量确认-检查响应结果:" + JSON.toJSONString(response));
        return Result.success(response);
    }

    @Override
    @FacadeInvoker(remark = "批量确认")
    @EpochTransactional(appCode = "ots_forecast_sales", dataSourceCode = "cr_ots")
    public Result<Boolean> batchConfirmUpdateForecast(ConfirmForecastRequest confirmForecastRequest) {
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        confirmForecastRequest.setOperatorName(loginUser.getRealName());
        boolean isSuccess = true;
        log.info("预报确认修改订单状态入参03 = {}", JSONObject.toJSONString(confirmForecastRequest));
        List<BatchCreateOrderRequest> confirmForecastStatuses = confirmForecastRequest.getConfirmForecastStatuses();
        if (CollectionUtils.isEmpty(confirmForecastStatuses)) {
            throw new FacadeException("OTS-04-001-00-15-047");
        }
        for (BatchCreateOrderRequest confirmForecastStatus : confirmForecastStatuses) {
            ForecastOrderEntity forecastOrderEntity = ForecastOrderFactory.confirmForecastStatus(confirmForecastStatus, confirmForecastRequest);
            isSuccess = forecastOrderEntity.confirmForecastStatus();
            //LogUtils.printOperateLog(forecastOrderEntity.getForecastOrderSDO().getId(),ForecastOrderLogEnum.REPLY.getForecastOrderLogValue(),"回复预报订单");
        }

        return Result.success(isSuccess);
    }

    @Override
    @FacadeInvoker
    //@EpochTransactional(appCode = "ots_forecast_sales", dataSourceCode = "cr_ots")  批量拒绝时单个子单拒绝消息已经发出、此时异常回滚没有意义
    public Result<Boolean> batchRefuseForecast(RefuseForecastRequest refuseForecastRequest) {
        Result<Boolean> result = batchRefuseForecastV2(refuseForecastRequest);
        //result空值判断
        if (Objects.isNull(result) || !result.isSuccess() || !result.getResult()) {
            log.error("ForecastOrderWriteServiceImpl#batchRefuseForecast_fail");
        }
        return result;
        /**
         *批量拒绝  根据id load出来数据 进行修改
         */
        /*log.info("预报拒绝入参 = {}", JSONObject.toJSONString(refuseForecastRequest));
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        try {
            if (CollectionUtils.isEmpty(refuseForecastRequest.getRefuseForecastDetailRequests())) {
                throw new FunctionException("OTS-04-001-00-15-008");
            }
            List<ForecastOrderLineEntity> forecastOrderLineEntities = ForecastOrderFactory.batchRefuseForecast(refuseForecastRequest.getRefuseForecastDetailRequests());
            List<ForecastOrderLineSDO> forecastOrderLineSDOList = new ArrayList<>();
            for (ForecastOrderLineEntity forecastOrderLineEntity : forecastOrderLineEntities) {
                ForecastOrderLineSDO forecastOrderLineSDO = forecastOrderLineEntity.getForecastOrderLineSDO();
                forecastOrderLineSDOList.add(forecastOrderLineSDO);
                OpLogModel.OpLogModelBuilder<String> builder = OpLogModel.builder();
                OpLogModel<String> opLogModel = builder.build();
                opLogModel.setModuleName(ModuleEnum.FORECAST_SALES.getModuleName());
                opLogModel.setModuleId(String.valueOf(ModuleEnum.FORECAST_SALES.getModuleId()));
                opLogModel.setObjectId(forecastOrderLineEntity.getForecastOrderLineSDO().getMainOrderId());
                opLogModel.setObjectName("id");
                opLogModel.setOperateType(OperateType.EDIT.getOperateType());
                opLogModel.setOperatorType(OperatorType.USER.getOperatorType());
                log.asyncMonitorObjectChangeV2(opLogModel);

                boolean analysis = forecastOrderLineWriteRepository.updateForAnalysis(forecastOrderLineSDO);
                if (analysis) {
                    String mainOrderId = forecastOrderLineSDO.getMainOrderId();
                    CountRefuseLineResponse countRefuseLineResponse = forecastOrderLineQueryService.countRefuseLine(new CountRefuseLineRequest() {{
                        setMainOrderId(mainOrderId);
                    }});
                    ForecastOrderSDO load = forecastOrderQueryRepository.load(mainOrderId);
//                    SearchForecastOrderRequest searchForecastOrderRequest=new SearchForecastOrderRequest();
//                    searchForecastOrderRequest.setId(mainOrderId);
//                    List<Integer> list=new ArrayList<>();
//                    list.add(2);
//                    list.add(3);
//                    searchForecastOrderRequest.setDetailStatusList(list);
                    ForecastOrderLineSDO orderLineSDO = new ForecastOrderLineSDO();
                    orderLineSDO.setMainOrderId(mainOrderId);
                    List<ForecastOrderLineSDO> forecastOrderLineSDOS = forecastOrderLineQueryRepository.queyrLineDetailList(orderLineSDO);
                    boolean bo = forecastOrderLineSDOS.stream().anyMatch(fo -> (fo.getStatus().intValue() == ForecastStatusEnum.WAITING_FOR_REPLY.getNumValue() || fo.getStatus().intValue() == ForecastStatusEnum.PARTIAL_REPLY.getNumValue()));
//                    Thread.sleep(200);//修改状态后再查询会导致部分回复无法转为全部回复
//                    Result<List<QueryForecastLineResponse>> listResult = forecastOrderLineQueryRepository.pageQuery(searchForecastOrderRequest);


                    if (bo) {
                        load.setStatus(ForecastStatusEnum.PARTIAL_REPLY.getNumValue());
                    } else {
                        load.setStatus(ForecastStatusEnum.COMPLETED.getNumValue());
                    }

                    if (Objects.nonNull(countRefuseLineResponse) && Objects.nonNull(countRefuseLineResponse.getRefuseType())) {
                        load.setRefuseStatus(countRefuseLineResponse.getRefuseType());
                    }
                    boolean b = forecastOrderWriteRepository.modifyForecast(load);
                    LogUtils.printOperateLog(load.getId(), ForecastOrderLogEnum.EDIT.getForecastOrderLogValue(), "编辑预报订单", loginUser);
                    //add by 皓晖 at 20211217 for 批量拒绝预报订单发消息 begin
                    this.sendMessage("ForecastRefused", forecastOrderLineSDO);
                    //add by 皓晖 at 20211217 for 批量拒绝预报订单发消息 end
                }
            }
            return Result.success(true);
        } catch (Exception e) {
            log.error("批量拒绝错误参数：", e);
            throw new FunctionException("OTS-04-001-00-15-009");
        }*/
    }

    private Result<Boolean> batchRefuseForecastV2(RefuseForecastRequest refuseForecastRequest) {
        /**
         *批量拒绝  根据id load出来数据 进行修改
         */
        log.info("预报拒绝入参 = {}", JSONObject.toJSONString(refuseForecastRequest));
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        if (CollectionUtils.isEmpty(refuseForecastRequest.getRefuseForecastDetailRequests())) {
            return Result.fail("OTS-04-001-00-15-008", "子单号不能为空");
        }
        Map<String, List<ForecastOrderLineSDO>> refuseForecastMap = ForecastOrderFactory.batchRefuseForecastNew(refuseForecastRequest.getRefuseForecastDetailRequests());
        boolean res = true;
        ErrorMessage errorMessage = new ErrorMessage();
        for (String orderId : refuseForecastMap.keySet()) {
            if (CollectionUtils.isEmpty(refuseForecastMap.get(orderId))) {
                continue;
            }
            // todo 和批量确认的key一样，防止并发
            String lockKey = "batch:" + orderId;
            try (RedisLock lock = new RedisLock("REDIS_CACHE", lockKey, 0, 30 * 1000)) {
                if (!lock.lock()) {
                    log.error("batchRefuseForecastV2加锁失败:" + lockKey);
                    errorMessage = ErrorMessage.code("OTS-04-001-00-15-038", "有部分单据正在参与其它操作，请稍后重试");
                    res = false;
                    continue;
                }
                for (ForecastOrderLineSDO orderLine : refuseForecastMap.get(orderId)) {
                    boolean analysis = forecastOrderLineWriteRepository.updateForAnalysis(orderLine);
                    // todo 后续可以优化，将更新主单状态放子单外部
                    if (analysis) {
                        String mainOrderId = orderLine.getMainOrderId();
                        CountRefuseLineResponse countRefuseLineResponse = forecastOrderLineQueryService.countRefuseLine(new CountRefuseLineRequest() {{
                            setMainOrderId(mainOrderId);
                        }});
                        ForecastOrderSDO load = forecastOrderQueryRepository.load(mainOrderId);
                        ForecastOrderLineSDO orderLineSDO = new ForecastOrderLineSDO();
                        orderLineSDO.setMainOrderId(mainOrderId);
                        List<ForecastOrderLineSDO> forecastOrderLineSDOS = forecastOrderLineQueryRepository.queyrLineDetailList(orderLineSDO);
                        boolean bo = forecastOrderLineSDOS.stream().anyMatch(fo -> (fo.getStatus().intValue() == ForecastStatusEnum.WAITING_FOR_REPLY.getNumValue() || fo.getStatus().intValue() == ForecastStatusEnum.PARTIAL_REPLY.getNumValue()));

                        if (bo) {
                            load.setStatus(ForecastStatusEnum.PARTIAL_REPLY.getNumValue());
                        } else {
                            load.setStatus(ForecastStatusEnum.COMPLETED.getNumValue());
                        }

                        if (Objects.nonNull(countRefuseLineResponse) && Objects.nonNull(countRefuseLineResponse.getRefuseType())) {
                            load.setRefuseStatus(countRefuseLineResponse.getRefuseType());
                        }
                        boolean b = forecastOrderWriteRepository.modifyForecast(load);
                        LogUtils.printOperateLog(load.getId(), ForecastOrderLogEnum.EDIT.getForecastOrderLogValue(), "编辑预报订单", loginUser);
                        //add by 皓晖 at 20211217 for 批量拒绝预报订单发消息 begin
                        this.sendMessage("ForecastRefused", orderLine);
                        //add by 皓晖 at 20211217 for 批量拒绝预报订单发消息 end
                    }
                }
            } catch (Exception e) {
                log.error("ForecastOrderWriteServiceImpl#batchRefuseForecastV2_fail");
                log.error("batchRefuseForecastNew|批量拒绝时发生异常:", e);
                errorMessage = ErrorMessage.code("OTS-04-001-00-15-038", "有部分单据拒绝失败，请稍后重试");
                res = false;
            }
        }
        if (!res) {
            //add data content
            return Result.fail(false, errorMessage.getErrorCode(), errorMessage.getErrorMessage());
        }
        return Result.success(true);
    }

    /**
     * 预报订单取消、预报订单拒绝发送消息
     */
    private void sendMessage(String tag, ForecastOrderLineSDO forecastOrderLineSDO) {
        try {
            String key = forecastOrderLineSDO.getId().toString();
            this.messageService.sendMessage("forecast_send_message", "CR_FORECAST",
                    tag, key, JSON.toJSONString(forecastOrderLineSDO));
        } catch (Exception e) {
            log.error("预报订单发送消息失败", e);
        }
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> updateForecastSubmit(ModifyForecastOrderRequest modifyForecastOrderRequest) {
        //获取主订单Id
        String id = modifyForecastOrderRequest.getForecastOrderSDOList().get(0).getId();
        //主订单部分数据进行更新
        if (StringUtils.isNotEmpty(id)) {
            //调用load方法查询 预报订单数据
            List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.modifyDraft(modifyForecastOrderRequest);
            for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {
                forecastOrderEntity.modifyDetailForecast();
            }
        }
        return Result.success(true);
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> batchActivityCheckForecast(ForecastOrderActivityRequest forecastOrderActivityRequest) {
        //根据传入Ids进行单据参数封装  更改订单处理状态
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.checkActivityForecast(forecastOrderActivityRequest);
        boolean isSuccess = true;
        for (ForecastOrderEntity forecastOrderEntity : forecastOrderEntities) {

            //按照主单维度进行查询活动
            isSuccess = forecastOrderEntity.activityUpdateDealForecast(JSONObject.parseObject(JSONObject.toJSONString(forecastOrderActivityRequest.getApiContext()),
                    ApiContext.class));

            //将数据的信息插入分析队列的表中
            List<DealLineSDO> collect = Nullable.stream(forecastOrderEntity.getForecastOrderSDO().getForecastOrderLineSDOList()).map(forecastOrderLineSDO -> {
                DealLineSDO dealLineSDO = new DealLineSDO();
                dealLineSDO.setForecastOrderLineId(forecastOrderLineSDO.getId().toString());
                dealLineSDO.setDealStatus(ForecastDealStatusSEO.CHECk_ED.getStatus());
                dealLineSDO.setDealType(ForecastDealTypeSEO.CHECK_ACTIVITIES.getDealTypeCode().toString());
                dealLineSDO.setModifierName(forecastOrderLineSDO.getModifierName());
                dealLineSDO.setModifierId(forecastOrderLineSDO.getModifierId());
                dealLineSDO.setDealTime(new Date());
                Date now = new Date();
                SimpleDateFormat f = new SimpleDateFormat("yyyyMMddhhmmss");
                String format = f.format(now);//20211015030520
                dealLineSDO.setBatchNumber(format);
                return dealLineSDO;
            }).collect(Collectors.toList());
            //创建分析队列的表中数据
            boolean b = dealLineWriteRepository.batchCreate(collect);
        }
        return Result.success(isSuccess);
    }

    /**
     * 确认活动
     *
     * @param forecastUpdateActivityRequest 活动更新请求
     * @return
     */
    @Override
    @FacadeInvoker
    public Result<Boolean> updateActivityForecast(ForecastUpdateActivityRequest forecastUpdateActivityRequest) {
        List<ForecastOrderActivityRequest> forecastOrderActivityRequestList = forecastUpdateActivityRequest.getForecastOrderActivityRequestList();
        boolean isSuccess = true;
        if (CollectionUtils.isNotEmpty(forecastOrderActivityRequestList)) {
            for (ForecastOrderActivityRequest forecastOrderActivityRequest : forecastOrderActivityRequestList) {
                ForecastOrderEntity forecastOrderEntity = ForecastOrderFactory.updateActivityForecast(forecastOrderActivityRequest);
//            //模型转换
                isSuccess = forecastOrderEntity.updateActivityForecast();
            }
        }

        return Result.success(isSuccess);
    }

    @Override
    @FacadeInvoker
    public Result<Boolean> deleteActivityForecast(DeleteActivityForecastRequest deleteActivityForecastRequest) {
        //拼装参数
        ForecastOrderEntity forecastOrderEntity = ForecastOrderFactory.deleteActivityForecast(deleteActivityForecastRequest);
        Boolean aBoolean = forecastOrderEntity.deleteActivityForecast();
        return Result.success(aBoolean);
    }

    @Override
    @FacadeInvoker
    public Result<SummaryForecastOrderResponse> summaryForecastOrder(SummaryForecastOrderRequest summaryForecastOrderRequest) {
        SummaryForecastOrderResponse summaryForecastOrderResponse = new SummaryForecastOrderResponse();
        if (CollectionUtils.isEmpty(summaryForecastOrderRequest.getIds())) {
            return Result.fail("OTS-04-001-00-15-008", "子单号不能为空");
        }
        List<String> ids = summaryForecastOrderRequest.getIds();
        PageResult<List<ForecastOrderLineSDO>> pageResult = forecastOrderLineQueryRepository.batchLoadList(ids);
        if (pageResult == null || CollectionUtils.isEmpty(pageResult.getContent())) {
            return Result.fail("OTS-04-001-00-15-009", "未查询到子单信息");
        }
        //根据发货仓进行分组
        Map<String, List<ForecastOrderLineSDO>> collect = Nullable.stream(pageResult.getContent()).collect(Collectors.groupingBy(ForecastOrderLineSDO::getWarehouseArea));
        if (collect.keySet().size() > 1) {
            return Result.fail("OTS-04-001-00-15-016", "所有单据必须为同一发货仓");
        }
        //乐观锁更新单据状态，防止并发
        UpdateCollectStatusRequest updateCollectStatusRequest = new UpdateCollectStatusRequest();
        updateCollectStatusRequest.setNewCollectStatus(1);
        updateCollectStatusRequest.setOldCollectStatus(0);
        updateCollectStatusRequest.setIds(ids);
        if (!forecastOrderLineWriteRepository.batchUpdateCollectStatus(updateCollectStatusRequest)) {
            return Result.fail("OTS-04-001-00-15-007", "批量更新子单汇总状态失败");
        }
        try {
            ForecastOrderEntity forecastOrderEntity = buildForecastOrderEntity(pageResult.getContent());
            String code = forecastOrderEntity.summaryForecastOrder();
            summaryForecastOrderResponse.setCode(code);
            return Result.success(summaryForecastOrderResponse);
        } catch (Exception e) {
            updateCollectStatusRequest.setNewCollectStatus(0);
            updateCollectStatusRequest.setOldCollectStatus(1);
            forecastOrderLineWriteRepository.batchUpdateCollectStatus(updateCollectStatusRequest);
            log.error("汇总预报单创建调拨单失败，原因=" + e.getMessage(), e);
            return Result.fail("OTS-04-001-00-15-026", e.getMessage());
        }
    }

    private ForecastOrderEntity buildForecastOrderEntity(List<ForecastOrderLineSDO> forecastOrderLineList) {
        List<ForecastOrderLineSDO> newForecastOrderLineSDOS = new ArrayList<>();
        Map<String, List<ForecastOrderLineSDO>> scitemMap = forecastOrderLineList.stream().collect(Collectors.groupingBy(ForecastOrderLineSDO::getScItemId));
        for (String scitemId : scitemMap.keySet()) {
            //获取出每种商品对应的子订单
            int countNumber = 0;
            List<ForecastOrderLineSDO> forecastOrderLineSDOS = scitemMap.get(scitemId);
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOS) {
                //将所有的数量装换成为库存单位数量  并累加
                if (StringUtils.isEmpty(forecastOrderLineSDO.getQuantity()) || StringUtils.isEmpty(forecastOrderLineSDO.getUnitConvert())) {
                    throw new FunctionException("OTS-04-001-00-15-019");
                }
                if ((!ObjectUtils.isEmpty(forecastOrderLineSDO.getQuantity()) && !ObjectUtils.isEmpty(forecastOrderLineSDO.getUnitConvert()))) {
                    int number = Integer.parseInt(forecastOrderLineSDO.getQuantity()) * Integer.parseInt(forecastOrderLineSDO.getUnitConvert());
                    countNumber += number;
                }
            }
            ForecastOrderLineSDO newForecastOrderLineSDO = new ForecastOrderLineSDO();
            BeanUtils.copyProperties(forecastOrderLineSDOS.get(0), newForecastOrderLineSDO);
            newForecastOrderLineSDO.setQuantity(String.valueOf(countNumber));
            newForecastOrderLineSDOS.add(newForecastOrderLineSDO);
        }
        ForecastOrderSDO forecastOrderSDO = forecastOrderQueryRepository.load(forecastOrderLineList.get(0).getMainOrderId());
        forecastOrderSDO.setForecastOrderLineSDOList(newForecastOrderLineSDOS);
        return ForecastOrderEntity.of(forecastOrderSDO);
    }

    @Override
    @FacadeInvoker
    public Result<List<OrderSDO>> batchCreateOrder(CretateOrderParamRequest cretateOrderParamRequest) {
        if (CollectionUtils.isEmpty(cretateOrderParamRequest.getIds())) {
            throw new FunctionException("OTS-04-001-00-15-004");
        }
        List<ForecastOrderEntity> forecastOrderEntities = ForecastOrderFactory.batchCreateForecastOrder(cretateOrderParamRequest.getIds());
        String sequenceNo = cretateOrderParamRequest.getSequenceNo();
        List<OrderSDO> orderSDOS = ForecastOrderFactory.batchCreateOrder(forecastOrderEntities, sequenceNo);
        //不知道为什么价update
//        for(ForecastOrderEntity forecastOrderEntity:forecastOrderEntities){
//            forecastOrderEntity.updateForecastOrderLine();
//        }
        return Result.success(orderSDOS);


    }

    @Override
    @FacadeInvoker
    public Result<List<ForecastOrderExportRequest>> createForecastOrderExport(CreateForecastOrderExportRequest createForecastOrderExportRequest) {
        LoginUser loginUser = epochLoginUserService.getLoginUser();
        Set<String> organizationCodeSet = Sets.newHashSet();
        Set<String> productGroupCodeSet = Sets.newHashSet();
        Set<String> channelCodeSet = Sets.newHashSet();
        Set<String> scItemCodeSet = Sets.newHashSet();
        Set<String> receiveAddressCodeSet = Sets.newHashSet();
        Set<String> saleUnitSet = Sets.newHashSet();
        Set<String> transportModeCodeSet = Sets.newHashSet();
        Set<String> wareHouseCodeSet = Sets.newHashSet();
        List<ForecastOrderExportRequest> orderLineToQueryActive = Lists.newArrayList();
        // 入参中行数据的集合
        long batchNo = System.currentTimeMillis();
        List<ForecastOrderExportRequest> orderExportRequestList = Optional.ofNullable(createForecastOrderExportRequest.getCreateForecastOrderExportRequest()).orElse(Lists.newArrayList());
        int size = orderExportRequestList.size();
        for (int i = 0; i < size; i++) {
            ForecastOrderExportRequest record = orderExportRequestList.get(i);
            if (record == null) {
                continue;
            }

            // 增加导入的时候的顺序字段
            Map reqFeatureMap = record.getFeatures();
            if (reqFeatureMap == null) {
                reqFeatureMap = Maps.newHashMap();
                record.setFeatures(reqFeatureMap);
            }
            reqFeatureMap.put(ForecastConstants.FORECAST_ORDER_IMPORT_INDEX, String.format("%s_%s", batchNo, String.format("%04d", i)));

            // 必填校验
            //预报订单类型校验
            if (StringUtils.isBlank(record.getOrderType())) {
                record.setErrorMessage("预报订单类型未填写");
                continue;
            }
            // 校验组织编码
            if (StringUtils.isBlank(record.getOrganizationCode())) {
                record.setErrorMessage("销售组织未填写");
                continue;
            } else {
                organizationCodeSet.add(StringUtils.trim(record.getOrganizationCode()));
            }

            //校验货品组信息
            if (StringUtils.isBlank(record.getProductGroupCode())) {
                record.setErrorMessage("货品组未填写");
                continue;
            } else {
                productGroupCodeSet.add(StringUtils.trim(record.getProductGroupCode()));
            }

            //校验渠道编码
            if (StringUtils.isBlank(record.getChannelCode())) {
                record.setErrorMessage("业务渠道未填写");
                continue;
            } else {
                channelCodeSet.add(StringUtils.trim(record.getChannelCode()));
            }

            //校验货品
            if (StringUtils.isBlank(record.getScItemId())) {
                record.setErrorMessage("货品未填写");
                continue;
            } else {
                scItemCodeSet.add(StringUtils.trim(record.getScItemId()));
            }

//            if (StringUtils.isBlank(record.getCustomerReferenceNo())) {
//                record.setErrorMessage("客户参考号未填写");
//                continue;
//            }

            //校验客户地址信息
            if (StringUtils.isBlank(record.getReceiveAddressCode())) {
                record.setErrorMessage("客户送达方未填写");
                continue;
            } else {
                receiveAddressCodeSet.add(StringUtils.trim(record.getReceiveAddressCode()));
            }

            if (StringUtils.isBlank(record.getSaleUnit())) {
                record.setErrorMessage("销售单位未填写");
                continue;
            } else {
                saleUnitSet.add(StringUtils.trim(record.getSaleUnit()));
            }

            //运输方式进行校验
            if (StringUtils.isNotBlank(record.getTransportModeCode())) {
                transportModeCodeSet.add(StringUtils.trim(record.getTransportModeCode()));
            }

            //校验发货仓库信息
            if (StringUtils.isBlank(record.getWareHouseCode())) {
                record.setErrorMessage("逻辑发货仓库未填写");
                continue;
            } else {
                wareHouseCodeSet.add(StringUtils.trim(record.getWareHouseCode()));
            }

            //校验预报数量   不能为空，是数字，不能大于多少
            if (StringUtils.isBlank(record.getQuantity()) || !StringUtils.isNumeric(record.getQuantity())) {
                record.setErrorMessage("数量未填写或填写内容不是数字");
                continue;
            }

            int quantityTmp = Integer.parseInt(record.getQuantity());
            if (quantityTmp <= 0 || quantityTmp > 10000000) {
                record.setErrorMessage("预报数量应在0到10000000之间");
                continue;
            }

            //校验备注信息   长度小于50
            if (StringUtils.isNotBlank(record.getRemark()) && record.getRemark().length() > 256) {
                record.setErrorMessage("备注信息长度不能超过255个字");
                continue;
            }

            //校验备注信息   长度小于30
            if (StringUtils.isNotBlank(record.getCustomerReferenceNo()) && record.getCustomerReferenceNo().length() > 30) {
                record.setErrorMessage("客户采购号长度不能超过30个字");
                continue;
            }
            if (Objects.nonNull(record.getCustomerExpectTDate())){
                if (Objects.equals(DateUtils.string2Date("9999-01-01 00:00:00"), record.getCustomerExpectTDate())) {
                    record.setErrorMessage("客户参考日期格式不正确");
                    continue;
                }
                Date firstTime = DateUtils.getFirstTime(new Date());
                if (record.getCustomerExpectTDate().compareTo(firstTime)<0){
                    record.setErrorMessage("客户参考日期不能小于当天");
                    continue;
                }
            }else {
                record.setErrorMessage("客户参考日期不能为空");
                continue;
            }


            //校验备注信息   长度小于50
            if (StringUtils.isNotBlank(record.getDetailRemark()) && record.getDetailRemark().length() > 256) {
                record.setErrorMessage("备注详情信息长度不能超过255个字");
                continue;
            }

            if (Objects.equals(record.getOrderType(), SaleOrderTag.REPLENISH_FORECAST.getCode())) {
                if (StringUtils.isBlank(record.getActivityCode())) {
                    record.setErrorMessage("补货活动ID必填");
                    continue;
                }
                if (StringUtils.isBlank(record.getActivityProjectCodeproject())) {
                    record.setErrorMessage("补货项目号必填");
                    continue;
                }
                if (StringUtils.isNotBlank(record.getActivityCode()) && StringUtils.isNotBlank(record.getActivityProjectCodeproject())) {
                    orderLineToQueryActive.add(record);
                }
            }
        }
        // 获取登陆人 信息
        EmployeeGetCurrentLoginResponse employeeGetCurrentLoginResponse = bcOtsService.employeeGetCurrentLogin();
        // 批量获取相关依赖的数据
        // 组织
        Map<String, List<OrganizationSDO>> organizationMap = batchQeuryOrgMap(organizationCodeSet);
        // 货品组
        Map<String, ScItemGroupResponse> productGroupMap = batchQueryProductGroup(productGroupCodeSet);

        List<String> ids = new ArrayList<>();
        organizationMap.entrySet().forEach(stringListEntry -> ids.addAll(stringListEntry.getValue().stream().map(OrganizationSDO::getId).collect(Collectors.toList())));
        // 渠道
        Map<String, OrganizationChannelRelationSDO> channelMap = batchQueryChannelMap(channelCodeSet, ids);
        // 货品
        Map<String, List<ScItemSDO>> scItemMap = batchQueryItem(scItemCodeSet);
        // 送达方
        Map<String, List<CustomerAddressSDO>> receiveAddressMap = batchQueryReceiveAddressMap(receiveAddressCodeSet, employeeGetCurrentLoginResponse);
        // 货品单位
        Map<String, List<ScItemUnit>> saleUnitMap = batchQuerySaleUnitMap(saleUnitSet);
        // 发货仓库
        Map<String, List<WarehouseInfo>> warehouseMap = batchQueryWareHouse(wareHouseCodeSet);
        // 运输方式
        Map<String, String> transportModeCodeMap = batchQueryTransportMode(transportModeCodeSet);
        // 查询活动  客户参考号+货品id 唯一key
        Map<String, List<ActivityInfoResponse>> activityInfoMap = activityQueryCode(orderLineToQueryActive);
        /*//活动id  和活动项目号
        Map<String, List<String>> activityIdMap=new HashMap<>();
        for (Map.Entry<String, List<ActivityInfoResponse>> stringListEntry : activityInfoMap.entrySet()) {
            List<String> activityTermId=Lists.newArrayList();
            List<ActivityInfoResponse> activityInfoResponses = stringListEntry.getValue();
            activityInfoResponses.stream().forEach(it->{Nullable.stream(it.getActivityTermList()).forEach(x->{activityTermId.add(x.getActivityTermId());});});
            activityIdMap.put(stringListEntry.getKey(),activityTermId);
        }*/
        //订单类型枚举 SaleOrderTag
        List<String> typeList = Lists.newArrayList();
        typeList.add(SaleOrderTag.STD_FORECAST.getCode());
        typeList.add(SaleOrderTag.CAR_FORECAST.getCode());
        typeList.add(SaleOrderTag.REPLENISH_FORECAST.getCode());
        for (ForecastOrderExportRequest record : orderExportRequestList) {
            if (StringUtils.isNotBlank(record.getErrorMessage())) {
                continue;
            }
            //订单类型枚举 SaleOrderTag
            if (!typeList.contains(StringUtils.trim(record.getOrderType()))) {
                record.setErrorMessage("订单类型无效");
                continue;
            }
            // 数据有效性校验
            if (MapUtils.isEmpty(organizationMap) || !organizationMap.containsKey(StringUtils.trim(record.getOrganizationCode()))) {
                record.setErrorMessage("销售组织无效");
                continue;
            }

            if (MapUtils.isEmpty(productGroupMap) || !productGroupMap.containsKey(StringUtils.trim(record.getProductGroupCode()))) {
                record.setErrorMessage("货品组无效");
                continue;
            }

            if (MapUtils.isEmpty(channelMap) || !channelMap.containsKey(StringUtils.trim(record.getChannelCode()))) {
                record.setErrorMessage("业务渠道无效");
                continue;
            }

            if (MapUtils.isEmpty(scItemMap) || !scItemMap.containsKey(StringUtils.trim(record.getScItemId()))) {
                record.setErrorMessage("货品无效");
                continue;
            }
            //补货活动时，校验活动项目号，活动id是否有效
            if (record.getOrderType().equals(SaleOrderTag.REPLENISH_FORECAST.getCode())) {
                String key = record.getCustomerReferenceNo() + record.getScItemId();
                List<ActivityInfoResponse> activityInfoResponses1 = activityInfoMap.get(key);
                List<String> collect = Nullable.stream(activityInfoResponses1).map(ActivityInfoResponse::getActivityId).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(activityInfoResponses1) || !collect.contains(StringUtils.trim(record.getActivityCode()))) {
                    record.setErrorMessage("补货活动ID无效");
                    continue;
                }
                List<String> activityProjectIds = Lists.newArrayList();
                for (ActivityInfoResponse activityInfoResponse : activityInfoResponses1) {
                    Nullable.stream(activityInfoResponse.getActivityTermList()).forEach(it -> {
                        activityProjectIds.add(it.getActivityTermId());
                    });
                }
                if (CollectionUtils.isEmpty(activityProjectIds)
                        || !activityProjectIds.contains(StringUtils.trim(record.getActivityProjectCodeproject()))) {
                    record.setErrorMessage("补货活动项目号无效");
                    continue;
                }
            }
            // 校验仓库信息 填写以填写为准，否则系统根据供货关系默认
            if (org.apache.commons.lang.StringUtils.isBlank(record.getWareHouseCode())) {
                List<CustomerAddressSDO> customerAddressSDOS = Optional.ofNullable(receiveAddressMap.get(record.getReceiveAddressCode())).orElse(Lists.newArrayList());
                if (CollectionUtils.isEmpty(customerAddressSDOS)) {
                    record.setErrorMessage("客户送达方无效");
                    continue;
                }
                //校验客户送达方是否有业务员
                List<CustomerAddressSDO> customerAddressSDOList = customerAddressSDOS.stream().filter(customerAddressSDO ->
                        StringUtils.isNotBlank(customerAddressSDO.getPrincipal())
                ).collect(Collectors.toList());
                if (CollectionUtils.isEmpty(customerAddressSDOList) || Objects.isNull(customerAddressSDOList.get(0))) {
                    record.setErrorMessage("客户送达方无对应的业务员");
                    continue;
                }
                CustomerAddressSDO customerAddressSDO = customerAddressSDOS.get(0);
                // 销售部门 需要 作为入参 更改供货关系customerCode为addressCode
                QueryAllocateRelationForOrderRequest request = QueryAllocateRelationForOrderRequest.builder()
                        .organizationCode(record.getOrganizationCode())
                        .saleChannelCode(customerAddressSDO.getOrgSaleChannelCode())
                        .addressCode(customerAddressSDO.getAddressCode())
                        .saleDepartmentCode(customerAddressSDO.getOrgSaleDepartmentCode()).build();
                Result<List<AllocateRelationSDO>> listResult = allocateRelationReadService.queryAllocateRelationForOrder(request);
                if (!ObjectUtils.isEmpty(listResult) && !CollectionUtils.isEmpty(listResult.getResult())) {
                    record.setWareHouseCode(listResult.getResult().get(0).getWareHouseCode());
                }
            }

            if (MapUtils.isEmpty(warehouseMap) || !warehouseMap.containsKey(StringUtils.trim(record.getWareHouseCode()))) {
                record.setErrorMessage("逻辑发货仓库无效");
                continue;
            }

            if (MapUtils.isEmpty(receiveAddressMap) || !receiveAddressMap.containsKey(StringUtils.trim(record.getReceiveAddressCode()))) {
                record.setErrorMessage("客户送达方无效");
                continue;
            }


            if (StringUtils.isNotBlank(record.getSaleUnit()) && (MapUtils.isEmpty(saleUnitMap) || !saleUnitMap.containsKey(StringUtils.trim(record.getSaleUnit())))) {
                record.setErrorMessage("销售单位无效");
                continue;
            }

            if (StringUtils.isNotBlank(record.getTransportModeCode()) && (MapUtils.isEmpty(transportModeCodeMap) || !transportModeCodeMap.containsKey(StringUtils.trim(record.getTransportModeCode())))) {
                record.setErrorMessage("运输方式无效");
                continue;
            }
        }

        List<ForecastOrderExportRequest> validList = Lists.newArrayList();
        Function<ForecastOrderExportRequest, String> groupKey = req -> req.getOrderType() + req.getOrganizationCode() + req.getProductGroupCode() + req.getChannelCode() + req.getReceiveAddressCode() + req.getCustomerReferenceNo();

        Map<String, List<ForecastOrderExportRequest>> validRecordGroup = orderExportRequestList.stream().collect(Collectors.groupingBy(groupKey));
        for (String addressCode : validRecordGroup.keySet()) {
            List<String> scItemCodes = Lists.newArrayList();
            List<ForecastOrderExportRequest> list = Optional.ofNullable(validRecordGroup.get(addressCode)).orElse(Lists.newArrayList());
            boolean validFlag = true;
            for (ForecastOrderExportRequest forecastOrderExportRequest : list) {
                // 重复子单校验
                String scItemId = forecastOrderExportRequest.getScItemId();
                String errorMessage = forecastOrderExportRequest.getErrorMessage();
                if (StringUtils.isBlank(errorMessage) && !scItemCodes.contains(scItemId)) {
                    scItemCodes.add(scItemId);
                    continue;
                }

                for (ForecastOrderExportRequest orderExportRequest : list) {
                    if (StringUtils.isBlank(orderExportRequest.getErrorMessage())) {
                        orderExportRequest.setErrorMessage(StringUtils.isNotBlank(errorMessage) ? "存在无效的子单行" : "存在重复的货品");
                    }
                    validFlag = false;
                }

                break;
            }
            if (validFlag) {
                validList.addAll(list);
            }
        }

        List<Future<Boolean>> createFutureList = Lists.newArrayList();
        Map<String, List<ForecastOrderExportRequest>> checkValidRecordGroup = validList.stream().collect(Collectors.groupingBy(groupKey));
        for (Map.Entry<String, List<ForecastOrderExportRequest>> mainForecastOrderEntry : checkValidRecordGroup.entrySet()) {
            Future<Boolean> createForecastOrderFeature = forecastSaleTaskExecutor.submit(() -> {
                try {
                    executeOne(createForecastOrderExportRequest, loginUser, organizationMap, productGroupMap, channelMap, scItemMap, receiveAddressMap, warehouseMap, transportModeCodeMap, activityInfoMap, mainForecastOrderEntry);
                } catch (Exception e) {
                    log.error(e, "预报订单导入， 主单创建失败, entry:{}", JSON.toJSONString(mainForecastOrderEntry));
                    return false;
                }

                return true;
            });

            createFutureList.add(createForecastOrderFeature);
        }

        for (Future<Boolean> booleanFuture : createFutureList) {
            try {
                log.info("批量导入创单结果：", booleanFuture.get());
            } catch (Exception e) {
                log.error("批量导入创单线程异常：", e);
            }
        }

        return Result.success(orderExportRequestList);

    }

    private void executeOne(CreateForecastOrderExportRequest createForecastOrderExportRequest, LoginUser loginUser, Map<String, List<OrganizationSDO>> organizationMap, Map<String, ScItemGroupResponse> productGroupMap, Map<String, OrganizationChannelRelationSDO> channelMap, Map<String, List<ScItemSDO>> scItemMap, Map<String, List<CustomerAddressSDO>> receiveAddressMap, Map<String, List<WarehouseInfo>> warehouseMap, Map<String, String> transportModeCodeMap, Map<String, List<ActivityInfoResponse>> activityInfoMap, Map.Entry<String, List<ForecastOrderExportRequest>> mainForecastOrderEntry) {
        ForecastOrderSDO sdo = new ForecastOrderSDO();

        String nextStringSequence = customSequenceAccessor.getNextStringSequence("ots_forecast_sales", "forecastOrderId");
        List<ForecastOrderExportRequest> forecastOrderExportRequests = Optional.ofNullable(mainForecastOrderEntry.getValue()).orElse(Lists.newArrayList());
        Date customerExpectTDate = forecastOrderExportRequests.get(0).getCustomerExpectTDate();
        //默认当天
        if (Objects.isNull(customerExpectTDate) || Objects.equals(customerExpectTDate, "")) {
            customerExpectTDate = new Date();
        }
        sdo.setOrderType(forecastOrderExportRequests.get(0).getOrderType());
        sdo.setRemark(forecastOrderExportRequests.get(0).getRemark());
        sdo.setOrderBizId(nextStringSequence);
        sdo.setStatus(ForecastStatusEnum.DRAFT.getNumValue());//需要变成待回复  ，先变成待提交，再调提交接口变成待回复  (可能导入订单状态直接为待提交，提交操作失败，需要手动提交)
        sdo.setCreateReason(forecastOrderExportRequests.get(0).getCreateReason());
        sdo.setOrganizationCode(forecastOrderExportRequests.get(0).getOrganizationCode());
        sdo.setProductGroupCode(forecastOrderExportRequests.get(0).getProductGroupCode());
        sdo.setChannelCode(forecastOrderExportRequests.get(0).getChannelCode());
        sdo.setReceiveAddressCode(forecastOrderExportRequests.get(0).getReceiveAddressCode());
        sdo.setTransportModeCode(forecastOrderExportRequests.get(0).getTransportModeCode());
        sdo.setWareHouseCode(forecastOrderExportRequests.get(0).getWareHouseCode());
        sdo.setCreatorId(createForecastOrderExportRequest.getCreateId());
        sdo.setCreatorName(createForecastOrderExportRequest.getCreateName());
        sdo.setGmtCreate(new Date());
        sdo.setCustomerExpectTDate(customerExpectTDate);
        sdo.setCustomerReferenceNo(forecastOrderExportRequests.get(0).getCustomerReferenceNo());

        // 获取渠道匹配的客户地址
        CustomerAddressSDO aimCustomerAddress = null;
        List<CustomerAddressSDO> customerAddressSDOS = Optional.ofNullable(receiveAddressMap.get(sdo.getReceiveAddressCode())).orElse(Lists.newArrayList());


        for (CustomerAddressSDO customerAddressSDO : customerAddressSDOS) {
            if (customerAddressSDO.getChannelCode().equals(sdo.getChannelCode())) {
                aimCustomerAddress = customerAddressSDO;
                break;
            }
        }

        if (aimCustomerAddress == null) {
            List<ForecastOrderExportRequest> targetValues = Optional.ofNullable(mainForecastOrderEntry.getValue()).orElse(Lists.newArrayList());
            for (ForecastOrderExportRequest targetValue : targetValues) {
                targetValue.setErrorMessage("收货地址&渠道不匹配");
            }
            return;
        }
        CustomerAddressSDO customerAddressSDO = null;
        //过滤掉没有业务员的客户收货地址
        List<CustomerAddressSDO> customerAddressSDOList = customerAddressSDOS.stream().filter(addressSDO ->
                StringUtils.isNotBlank(addressSDO.getPrincipal())
        ).collect(Collectors.toList());

        for (CustomerAddressSDO address : customerAddressSDOList) {
            if (address.getChannelCode().equals(sdo.getChannelCode())) {
                customerAddressSDO = address;
                break;
            }
        }
        if (customerAddressSDO == null) {
            List<ForecastOrderExportRequest> targetValues = Optional.ofNullable(mainForecastOrderEntry.getValue()).orElse(Lists.newArrayList());
            for (ForecastOrderExportRequest targetValue : targetValues) {
                targetValue.setErrorMessage("客户送达方没有分派销售负责人");
            }
            return;
        }

//        customerAddressSDO = aimCustomerAddress;
        sdo.setCustomerCode(customerAddressSDO.getCustomerCode());
        sdo.setCustomerName(customerAddressSDO.getCustomerName());
//            sdo.setOrganizationCode(customerAddressSDO.getOrgSaleOrganizationCode());
//            sdo.setOrganizationName(customerAddressSDO.getOrgSalesOrganizationName());
        //add by myw
        sdo.setBisUnitCode(customerAddressSDO.getOrgBussinessUnitCode());
        sdo.setDepartmentCode(customerAddressSDO.getOrgSaleDepartmentCode());
        sdo.setDepartmentName(customerAddressSDO.getOrgSalesDepartmentName());
        sdo.setSaleChannelCode(customerAddressSDO.getOrgSaleChannelCode());
        sdo.setSaleChannelName(customerAddressSDO.getOrgSalesChannelName());
        sdo.setChannelCode(customerAddressSDO.getChannelCode());
        sdo.setSalesmanCode(customerAddressSDO.getPrincipal());
        sdo.setSalesmanName(customerAddressSDO.getPrincipalName());
        sdo.setChannelName(customerAddressSDO.getChannelName());
        sdo.setContact(customerAddressSDO.getContactName());
        sdo.setContactPhone(customerAddressSDO.getCellphoneNumber());
        sdo.setReceiveDetailAddress(customerAddressSDO.getAddressName());
        sdo.setProductGroupCode(customerAddressSDO.getItemGroup());
        sdo.setVaildBeginTime(new Date());
        sdo.setProductGroupName(customerAddressSDO.getItemGroupName());

        sdo.setWareHouseName(warehouseMap.get(sdo.getWareHouseCode()).get(0).getName());
        sdo.setWareHouseCode(warehouseMap.get(sdo.getWareHouseCode()).get(0).getId());

        //通过导入参数外部编码查询名称和内部编码
        sdo.setOrganizationName(organizationMap.get(sdo.getOrganizationCode()).get(0).getName());
        sdo.setOrganizationCode(organizationMap.get(sdo.getOrganizationCode()).get(0).getId());

        sdo.setChannelName(channelMap.get(sdo.getChannelCode()).getName());
        sdo.setChannelCode(channelMap.get(sdo.getChannelCode()).getCode());

        sdo.setDepartmentCode(customerAddressSDO.getOrgSaleDepartmentCode());
        sdo.setDepartmentName(customerAddressSDO.getOrgSalesDepartmentName());

        sdo.setProductGroupName(productGroupMap.get(sdo.getProductGroupCode()).getName());
        sdo.setProductGroupCode(productGroupMap.get(sdo.getProductGroupCode()).getCode());

        //调用查询客户信息
        if (StringUtils.isNotBlank(sdo.getCustomerCode())) {
            CustomerRequest request = new CustomerRequest();
            request.setCode(sdo.getCustomerCode());
            Result<CustomerSDO> result = customerQueryService.queryCustomer(request);
            if (result.isSuccess() && Objects.nonNull(result.getResult()) && Objects.nonNull(result.getResult().getCode())) {
                sdo.setCustomerName(result.getResult().getName());
                sdo.setCustomerCode(result.getResult().getCode());
            }
        }

        sdo.setTransportModeName(transportModeCodeMap.get(sdo.getTransportModeCode()));

        //导入的预报单增加source 数据来源到features
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.put(ForecastConstants.OS, "import");
        sdo.setFeatures(hashMap);
        List<ForecastOrderLineSDO> forecastOrderLineSDOS = new ArrayList<>();
        sdo.setForecastOrderLineSDOList(forecastOrderLineSDOS);

        boolean createFlag = true;
        int i = 1;
        for (ForecastOrderExportRequest it : forecastOrderExportRequests) {

            Map map = new HashMap();
            map.put(ForecastConstants.ACTIVITY_NUMBER, it.getActivityProjectCodeproject());
            map.put(ForecastConstants.FORECAST_ORDER_IMPORT_INDEX, Optional.ofNullable(it.getFeatures()).orElse(Maps.newHashMap()).getOrDefault(ForecastConstants.FORECAST_ORDER_IMPORT_INDEX, ""));
            ForecastOrderLineSDO build = ForecastOrderLineSDO.builder()
                    .scItemId(it.getScItemId())
                    .quantity(it.getQuantity())
                    .saleUnit(it.getSaleUnit())
                    .serialNumber(String.valueOf(i * 10))
                    .status(2)
                    .warehouseArea(sdo.getWareHouseCode())
                    .mainOrderBizId(sdo.getOrderBizId())
                    .detailRemark(it.getDetailRemark())
                    .saleUnitCode(it.getSaleUnit())
                    .activityCode(it.getActivityCode())
                    //.mainOrderId(save)
                    .dealStatus(ForecastDealStatusSEO.WAITING_DEAL.getStatus())
                    .customerCode(sdo.getCustomerCode())
                    .customerName(sdo.getCustomerName())
                    .activityCode(it.getActivityCode())
                    .activityNumber(it.getActivityProjectCodeproject())
                    .features(map).build();
            i++;
            //补货预报订单加活动信息  且匹配到活动信息
            String key = forecastOrderExportRequests.get(0).getCustomerReferenceNo() + forecastOrderExportRequests.get(0).getScItemId();
            if (it.getOrderType().equals(SaleOrderTag.REPLENISH_FORECAST.getCode()) && CollectionUtils.isNotEmpty(activityInfoMap.get(key))) {

                List<ActivityInfoResponse> activityInfoResponses = activityInfoMap.get(key);
                List<ActivityInfoResponse> realActivityList = Nullable.stream(activityInfoResponses).filter(e -> Objects.equals(e.getActivityId(), it.getActivityCode())).collect(Collectors.toList());
                ActivityInfoResponse activityInfoResponse = realActivityList.get(0);//补货活动匹配到的活动
                Nullable.stream(activityInfoResponse.getActivityTermList()).forEach(active -> {
                    if (Objects.equals(active.getActivityTermId(), it.getActivityProjectCodeproject())) {
                        build.setActivityCode(activityInfoResponse.getActivityId());
                        build.setActivityName(activityInfoResponse.getActivityNoteName());
                        build.setIntensityOfActivityDesc(active.getIntensityOfActivityDesc());
                        build.setActivityNumber(active.getActivityTermId());
                        build.setActivityVersion(active.getVersion());
                        build.setActivityRemainingFee(active.getActivityRemainingFee());
                        build.setActivityRemainingQuantity(active.getActivityRemainingQuantity());
                    }
                });
            }
            ScItemSDO scItemSDO = scItemMap.get(build.getScItemId()).get(0);
            build.setScItemOutCode(scItemSDO.getOuterId());
            build.setScItemTitle(scItemSDO.getTitle());
            build.setScItemId(scItemSDO.getScItemId());
            build.setGoodsCode(scItemSDO.getOuterId());
            Map<String, String> features = scItemSDO.getFeatures();
            if (MapUtils.isNotEmpty(features)) {
                String unitName = features.get("unit");
                String unitCode = features.get("unitName");
                if (StringUtils.isNotBlank(unitName)) {
                    build.setInventoryUnit(unitName);
                }
                if (StringUtils.isNotBlank(unitCode)) {
                    build.setInventoryUnitCode(unitCode);
                }
                build.setCategoryCode(features.get("category"));
                build.setCategoryDesc(features.get("categoryDesc"));
                build.setCategoryChildCode(features.get("categoryChildCode"));
                build.setCategoryChildDesc(features.get("categoryChildDesc"));
            }

            QuerySaleUnitRequest querySaleUnitRequest = QuerySaleUnitRequest.builder().scItemId(scItemSDO.getScItemId()).build();
            querySaleUnitRequest.setInventoryUnit(build.getInventoryUnit());
            querySaleUnitRequest.setInventoryUnitCode(build.getInventoryUnitCode());
            querySaleUnitRequest.setUnitConvert("1");
            Result<List<SelectCombox>> querySaleUnitList = forecastOrderLineQueryService.querySaleUnitList(querySaleUnitRequest);
            if (querySaleUnitList.isSuccess() && Objects.nonNull(querySaleUnitList.getResult())) {
                List<SelectCombox> result = querySaleUnitList.getResult();
                Map<String, SelectCombox> unitMap = new HashMap<>();
                Nullable.stream(result).forEach(t -> {
                    unitMap.put(t.getValue(), t);
                });
                SelectCombox selected = unitMap.get(build.getSaleUnitCode());
                if (selected != null) {
                    build.setSaleUnit(selected.getLabel());
                    build.setUnitConvert(selected.getExt());
                }

                SelectCombox inventoryMap = unitMap.get(build.getSaleUnitCode());
                if (inventoryMap != null) {
                    build.setInventoryUnit(inventoryMap.getLabel());
                }
            }

            List<SubOrderInfo> forecastOrderLine = queryOrderLinePrice(sdo, build);

            Map<String, Object> dailyInventory = queryDailyInv(sdo, build);
            if ((boolean) dailyInventory.getOrDefault("limitSwitch", false)) {
                if (StringUtils.isNotBlank(String.valueOf(dailyInventory.get("dailyInventory")))) {
                    BigDecimal dailyInventory1 = new BigDecimal(String.valueOf(dailyInventory.get("dailyInventory"))).setScale(3, RoundingMode.DOWN);
                    BigDecimal bigDecimal = new BigDecimal(build.getQuantity()).setScale(3, RoundingMode.DOWN);
                    if (bigDecimal.compareTo(dailyInventory1) > 0) {
                        for (ForecastOrderExportRequest forecastOrderExportRequest : mainForecastOrderEntry.getValue()) {
                            forecastOrderExportRequest.setErrorMessage("已配置每日库存分解限量，提报量不能大于每日库存分解数量");
                            /*forecastOrderExportRequest.setErrorMessage("存在无价格的商品");*/
                        }
                        it.setErrorMessage("已配置每日库存分解限量，提报量不能大于每日库存分解数量");
                        createFlag = false;
                        break;
                    }
                }
            }

            //加上对于价格为正数的判断
            if (CollectionUtils.isNotEmpty(forecastOrderLine) && forecastOrderLine.get(0).getUnitPrice() != null && forecastOrderLine.get(0).getUnitPrice() >= 0) {
                build.setUnitPrice(forecastOrderLine.get(0).getUnitPrice());
                if (Objects.nonNull(forecastOrderLine.get(0).getUnitPrice())) {
                    build.setTotalFee(forecastOrderLine.get(0).getUnitPrice() * Integer.parseInt(build.getQuantity()));
                }
            } else {
                for (ForecastOrderExportRequest forecastOrderExportRequest : mainForecastOrderEntry.getValue()) {
                    forecastOrderExportRequest.setErrorMessage("存在异常价格的商品");
                    /*forecastOrderExportRequest.setErrorMessage("存在无价格的商品");*/
                }
                it.setErrorMessage("商品获取价格失败");
                createFlag = false;
                break;
            }


            forecastOrderLineSDOS.add(build);
        }

        if (createFlag) {
            String save = forecastOrderWriteRepository.save(sdo);
            LogUtils.printOperateLog(save, ForecastOrderLogEnum.CREATE.getForecastOrderLogValue(), "创建预报订单", loginUser);
            List<ForecastOrderLineSDO> forecastOrderLineSDOList = sdo.getForecastOrderLineSDOList();
            for (ForecastOrderLineSDO forecastOrderLineSDO : forecastOrderLineSDOList) {
                forecastOrderLineSDO.setMainOrderId(save);
                forecastOrderLineWriteRepository.save(forecastOrderLineSDO);
            }
            //创建完成主单子单，进行订单提交
            try {
                SubmitForecastRequest submitForecastRequest = new SubmitForecastRequest();
                com.epoch.app.otsforecastsales.model.dto.ApiContext apiContext = new com.epoch.app.otsforecastsales.model.dto.ApiContext();
                apiContext.setEmployeeId(loginUser.getEmpId());
                apiContext.setEmployeeName(loginUser.getRealName());
                submitForecastRequest.setApiContext(apiContext);
                List<ForecastOrderSDO> forecastOrderSDOList = Lists.newArrayList(ForecastOrderSDO.builder().id(save).build());
                submitForecastRequest.setForecastOrderSDOList(forecastOrderSDOList);
                submitForecast(submitForecastRequest);
            } catch (Exception e) {
                log.error("导入预报订单提交失败,订单状态为待提交", e);
            }

        }
    }

    private Map<String, Object> queryDailyInv(ForecastOrderSDO sdo, ForecastOrderLineSDO build) {
        HashMap<String, Object> stringObjectHashMap = new HashMap<>();

        String organizationCode = sdo.getOrganizationCode();
        String channelCode = sdo.getChannelCode();
        String departmentCode = sdo.getDepartmentCode();
        String salesmanCode = sdo.getSalesmanCode();
        String wareHouseCode = sdo.getWareHouseCode();

        QueryAllotRequest queryAllotRequest = new QueryAllotRequest();
        queryAllotRequest.setOrganizationCode(organizationCode);
        queryAllotRequest.setChannelCode(channelCode);
        queryAllotRequest.setDepartmentCode(departmentCode);
        queryAllotRequest.setSalesmanCode(salesmanCode);
        queryAllotRequest.setWarehouseCode(wareHouseCode);
        queryAllotRequest.setScItemId(build.getScItemId());
        Result<QueryAllotResponse> result = inventoryAllotQueryService.queryAllot(queryAllotRequest);
        stringObjectHashMap.put("limitSwitch", false);
        if (Objects.nonNull(result) && Objects.nonNull(result.getResult())) {
            stringObjectHashMap.put("limitSwitch", result.getResult().getMainLimitSwitch());
            stringObjectHashMap.put("dailyInventory", result.getResult().getRemainingQuantity());
        }
        return stringObjectHashMap;
    }

    private List<SubOrderInfo> queryOrderLinePrice(ForecastOrderSDO sdo, ForecastOrderLineSDO build) {
        QueryGoodsDetailRequest queryGoodsDetailRequest = new QueryGoodsDetailRequest();
        ForecastOrderSDO tmpSdo = new ForecastOrderSDO();
        BeanUtils.copyProperties(sdo, tmpSdo);
        List<ForecastOrderLineSDO> tmpForecastOrderLineSDOS = new ArrayList<>();
        tmpSdo.setForecastOrderLineSDOList(tmpForecastOrderLineSDOS);
        tmpForecastOrderLineSDOS.add(build);
        String s1 = JSONObject.toJSONString(tmpSdo);
        MainOrderInfo mainOrderInfo = JSONObject.parseObject(s1, MainOrderInfo.class);
        queryGoodsDetailRequest.setForecastOrderSDO(mainOrderInfo);
        List<SubOrderInfo> forecastOrderLine = priceQueryUtils.queryGoodsDetail(queryGoodsDetailRequest);
        return forecastOrderLine;
    }

    private Map<String, String> batchQueryTransportMode(Set<String> transportModeCodeSet) {
        Map<String, String> transportModeCodeMap = Maps.newHashMap();
        for (String transportModeCode : transportModeCodeSet) {
            QueryDictionaryRequest queryDictionaryRequest = new QueryDictionaryRequest();
            queryDictionaryRequest.setDictCode("shipMethod");
            queryDictionaryRequest.setValueCode(transportModeCode);
            Result<String> stringResult = dictionaryQueryService.queryValueNameByCode(queryDictionaryRequest);
            if (stringResult != null && StringUtils.isNotBlank(stringResult.getResult())) {
                transportModeCodeMap.put(transportModeCode, stringResult.getResult());
            }
        }

        return transportModeCodeMap;
    }

    /**
     * 获取 登录人有权限的发货仓  和 导入发货仓 交集
     *
     * @param wareHouseCodeSet
     * @return
     */
    private Map<String, List<WarehouseInfo>> batchQueryWareHouse(Set<String> wareHouseCodeSet) {
        Map<String, List<WarehouseInfo>> warehouseMap = Maps.newHashMap();

        QueryCargoZoneListWithAccessRequest cargoZoneListRequest =
                QueryCargoZoneListWithAccessRequest.builder()
                        .model(3)
                        //.limit(500)
                        .typeList(Stream.of(1, 2, 3, 4, 5).collect(Collectors.toList()))
                        .build();
        // 获取登陆人 仓库权限
        QueryCargoZoneListWithAccessResponse searchCargoZoneListForPageResponse = bcOtsService.queryCargoZoneListWithAccess(cargoZoneListRequest);
        if (ObjectUtils.isEmpty(searchCargoZoneListForPageResponse)) {
            return warehouseMap;
        }
        List<WarehouseInfo> result = searchCargoZoneListForPageResponse.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return warehouseMap;
        }
        warehouseMap = result.stream()
                .filter(warehouseInfo -> wareHouseCodeSet.contains(warehouseInfo.getCode()))
                .collect(Collectors.groupingBy(WarehouseInfo::getCode));


//        for (String wareHouseCode : wareHouseCodeSet) {
//            WmsQueryWarehouseZoneListRequest byIdRequest = new WmsQueryWarehouseZoneListRequest();
//            byIdRequest.setCode(wareHouseCode);
//            WmsQueryWarehouseZoneListResponse warehouseInfoResult = unifiedInventoryService.wmsQueryWarehouseZoneList(byIdRequest);
//            if (warehouseInfoResult != null && warehouseInfoResult.getResult() != null) {
//                warehouseMap.put(wareHouseCode, warehouseInfoResult.getResult());
//            }
//        }
        return warehouseMap;
    }

    private Map<String, List<ScItemUnit>> batchQuerySaleUnitMap(Set<String> saleUnitSet) {
        Map<String, List<ScItemUnit>> receiveAddressCodeMap = Maps.newHashMap();
        for (String saleUnit : saleUnitSet) {
            ScItemUnitLoadListRequest scItemUnitLoadListRequest = ScItemUnitLoadListRequest
                    .newScItemUnitLoadListRequestBuilder().code(saleUnit).build();
            Result<List<ScItemUnit>> listResult1 = scItemUnitService.loadScItemUnitList(scItemUnitLoadListRequest);
            receiveAddressCodeMap.put(saleUnit, listResult1.getResult());
        }

        return receiveAddressCodeMap;
    }

    /**
     * 获取 登录人有权限的收货地址  和 导入收货地址 交集
     *
     * @param receiveAddressCodeSet
     * @param employeeGetCurrentLoginResponse
     * @return
     */
    private Map<String, List<CustomerAddressSDO>> batchQueryReceiveAddressMap
    (Set<String> receiveAddressCodeSet, EmployeeGetCurrentLoginResponse employeeGetCurrentLoginResponse) {
        Map<String, List<CustomerAddressSDO>> receiveAddressCodeMap = Maps.newHashMap();

        // 获取 登录人 拥有权限的 收货地址
        CustomerAddressBatchRequest addressBatchRequest = CustomerAddressBatchRequest.builder().addressCodes(new ArrayList<>(receiveAddressCodeSet)).build();
        addressBatchRequest.setStatus(1);

        String relatedOrganizationId = employeeGetCurrentLoginResponse.getRelatedOrganizationId();
        switch (employeeGetCurrentLoginResponse.getRelatedOrganizationType()) {
            case "103":
                // 分子公司
                addressBatchRequest.setOrgBussinessUnitCode(relatedOrganizationId);
                break;
            case "104":
                // 销售组织
                addressBatchRequest.setOrgSaleOrganizationCode(relatedOrganizationId);
                break;
            case "105":
                // 销售渠道
                addressBatchRequest.setOrgSaleChannelCode(relatedOrganizationId);
                break;
            case "106":
                // 销售部门
                addressBatchRequest.setOrgSaleDepartmentCode(relatedOrganizationId);
                break;
        }
        //1为启用状态 0禁用状态  -1非业务状态
        addressBatchRequest.setStatus(1);
        Result<List<CustomerAddressSDO>> listResult = customerAddressQueryService.batchQueryCustomerAddress(addressBatchRequest);
        List<CustomerAddressSDO> result = CollectionUtils.isEmpty(listResult.getResult()) ? new ArrayList<>() : listResult.getResult();
        receiveAddressCodeMap = result.stream()
                .filter(customerAddressSDO -> receiveAddressCodeSet.contains(customerAddressSDO.getAddressCode()))
                .collect(Collectors.groupingBy(CustomerAddressSDO::getAddressCode));


//        for (String receiveAddressCode : receiveAddressCodeSet) {
//            QueryAddressRequest queryAddressRequest = new QueryAddressRequest();
//            queryAddressRequest.setAddressCode(receiveAddressCode);
//            Result<List<CustomerAddressSDO>> customerAddress = customerAddressQueryService.pageQueryCustomerAddress(queryAddressRequest);
//            if (customerAddress != null && customerAddress.getResult() != null) {
//                receiveAddressCodeMap.put(receiveAddressCode, customerAddress.getResult());
//            }
//        }


        return receiveAddressCodeMap;
    }

    private Map<String, List<ScItemSDO>> batchQueryItem(Set<String> scItemCodeSet) {
        SearchScItemRequest searchScItemRequest = new SearchScItemRequest();
        SearchReqDTO searchReqDTO = new SearchReqDTO();
        List<String> list = Lists.newArrayList(scItemCodeSet);
        searchReqDTO.setOuterIdList(list);
        searchScItemRequest.setSearchReqDTO(searchReqDTO);
        searchScItemRequest.setPageNum(1);
        searchScItemRequest.setPageSize(list.size());
        Result<List<ScItemSDO>> listResult = baseDataService.searchScItem(searchScItemRequest);
        if (listResult != null && listResult.getResult() != null) {
            return listResult.getResult().stream().collect(Collectors.groupingBy(ScItemSDO::getOuterId));
        }
        return null;
    }

    /**
     * 获取 登录人有权限的业务渠道  和 导入业务渠道 交集
     *
     * @param channelCodeSet
     * @param ids
     * @return
     */
    private Map<String, OrganizationChannelRelationSDO> batchQueryChannelMap(Set<String> channelCodeSet, List<String> ids) {
        Map<String, OrganizationChannelRelationSDO> channelMap = Maps.newHashMap();

        // 获取 登陆人 拥有权限的 渠道
        GetOrgChannelRelationByOrgId2Request request = GetOrgChannelRelationByOrgId2Request.builder().ids(ids).build();
        Result<List<OrganizationChannelRelationSDO>> orgChannelRelationByOrgId2 = otsPlatformEnhanceService.getOrgChannelRelationByOrgId2(request);
        if (ObjectUtils.isEmpty(orgChannelRelationByOrgId2)) {
            return channelMap;
        }
        List<OrganizationChannelRelationSDO> result = orgChannelRelationByOrgId2.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return channelMap;
        }

//        for (String channel : channelCodeSet) {
//            QueryChannelRequest baselineBatchQueryChannelsRequest = new QueryChannelRequest();
//            baselineBatchQueryChannelsRequest.setOutCode(channel);
//            //调用查询渠道信息
//            Result<ChannelResponse> result = channelService.queryChannelDetail(baselineBatchQueryChannelsRequest);
//            if (result != null && result.getResult() != null) {
//                channelMap.put(channel, result.getResult());
//            }
//        }
        channelMap = result.stream()
                .filter(organizationChannelRelationSDO -> channelCodeSet.contains(organizationChannelRelationSDO.getCode()))
                .collect(Collectors.toMap(OrganizationChannelRelationSDO::getOutCode, o -> o, (v1, v2) -> v1));
        return channelMap;
    }

    private Map<String, ScItemGroupResponse> batchQueryProductGroup(Set<String> productGroupCodeSet) {
        Map<String, ScItemGroupResponse> productGroupMap = Maps.newHashMap();
        for (String productGroup : productGroupCodeSet) {
            QueryScItemGroupRequest request = new QueryScItemGroupRequest();
            request.setCode(productGroup);
            Result<ScItemGroupResponse> result = scItemGroupQueryService.getScItemGroup(request);
            if (result != null && result.getResult() != null && StringUtils.isNotBlank(result.getResult().getCode())) {
                productGroupMap.put(productGroup, result.getResult());
            }
        }
        return productGroupMap;
    }

    /**
     * 获取 登录人有权限的销售组织  和 导入销售组织 交集
     *
     * @param organizationCodeSet
     * @return
     */
    private Map<String, List<OrganizationSDO>> batchQeuryOrgMap(Set<String> organizationCodeSet) {
        // 权限控制在这里加
        List<OrganizationSDO> loginOrganizationCode = getLoginOrganizationCode(OrganizationTypeEnum.SALES_ORGANIZATION.getCode());
        Map<String, List<OrganizationSDO>> organizationMap =
                loginOrganizationCode.stream()
                        .filter(organizationSDO -> organizationCodeSet.contains(organizationSDO.getCode()))
                        .collect(Collectors.groupingBy(OrganizationSDO::getCode));

//        GetOrganizationsByOutCodesRequest request = new GetOrganizationsByOutCodesRequest();
//        List<String> list = Lists.newArrayList(organizationCodeSet);
//        request.setOutCodes(list);
//        Result<List<OrganizationSDO>> result = organizationQueryService.getOrganizationsByOutCodes(request);
//        if (result != null && result.getResult() != null) {
//            Map<String, List<OrganizationSDO>> organizationMap = result.getResult().stream().collect(Collectors.groupingBy(OrganizationSDO::getCode));
//            return organizationMap;
//        }

        return organizationMap;
    }

    @Override
    @FacadeInvoker // TBD 消息是否可以重投？
    public Result<Void> forecastOrderStatusBack(ForecastOrderStatusBackRequest msg) {
        TradeMessageSDO tradeMessageSDO = JSONObject.parseObject(msg.getMessage(), TradeMessageSDO.class);

        if (CollectionUtils.isEmpty(tradeMessageSDO.getAffectLineIds())) {
            throw new FunctionException("OTS-04-001-00-15-029");
        }
        if (CollectionUtils.isEmpty(tradeMessageSDO.getOrderSDO().getOrderLineSDOS())) {
            throw new FunctionException("OTS-04-001-00-15-030");
        }
        // 受影响的销售子单
        List<OrderLineSDO> sdoList = tradeMessageSDO.getOrderSDO().getOrderLineSDOS()
                .stream()
                .filter(orderLine ->
                        tradeMessageSDO.getAffectLineIds().contains(orderLine.getId()))
                .collect(Collectors.toList());
        if (CollectionUtils.isEmpty(sdoList)) {
            return Result.success(null);
        }
        //这里销售子单 与 预报子单是1比1
        // 销售子单map
        Map<String, OrderLineSDO> orderLineMap = Maps.newHashMap();
        // 预报子单id
        //orderLineMap = sdoList
        //    .stream()
        //    .filter(lineSDO -> MapUtils.isEmpty(lineSDO.getFeatures())
        //            || !"gift".equals(lineSDO.getFeatures().get("giftFlag")))
        //    .collect(Collectors.toMap(OrderLineSDO::getFrontOrderLineId, o -> o));

        // 这里只取主品子单进行回退，如果是赠品等场景的子单不需要回退，像特价场景按正常订单处理
        sdoList.forEach(orderLineSDO -> {
            if (StringUtils.endsWith(orderLineSDO.getSerialNumber(), "0")) {
                orderLineMap.put(orderLineSDO.getFrontOrderLineId(), orderLineSDO);
            }

            //if (orderLineMap.get(orderLineSDO.getFrontOrderLineId()) == null) {
            //    orderLineMap.put(orderLineSDO.getFrontOrderLineId(), orderLineSDO);
            //} else {
            //    OrderLineSDO oldOrderLineSDO = orderLineMap.get(orderLineSDO.getFrontOrderLineId());
            //    Integer newSerialNo = Integer.valueOf(orderLineSDO.getSerialNumber());
            //    Integer oldSerialNo = Integer.valueOf(oldOrderLineSDO.getSerialNumber());
            //    if (newSerialNo < oldSerialNo) {
            //        orderLineMap.put(orderLineSDO.getFrontOrderLineId(), orderLineSDO);
            //    }
            //}

        });

        // 销售子单对应的预报子单
        List<String> idList = Lists.newArrayList(orderLineMap.keySet());
        PageResult<List<ForecastOrderLineSDO>> result = forecastOrderLineQueryRepository.batchLoadList(idList);
        if (CollectionUtils.isEmpty(result.getContent())) {
            return Result.success(null);
        }
        List<ForecastOrderLineSDO> forecastOrderLines = Lists.newArrayList();
        Map<String, OrderLineSDO> finalOrderLineMap = orderLineMap;
        result.getContent().forEach(forecastOrderLine -> {
            String id = String.valueOf(forecastOrderLine.getId());
            OrderLineSDO orderLineSDO = finalOrderLineMap.get(id);
            //销售子单货品数量
            int totalScItemAmount = orderLineSDO.getScItemSDO().getQuantity();
            // 预报子单数量
            int totalQuantity = Integer.parseInt(forecastOrderLine.getQuantity());
            if (totalScItemAmount > totalQuantity) {
                throw new FunctionException("OTS-04-001-00-15-031");
            }
            // 预报子单累计回复数量
            Integer actualTotalReplyAmount = forecastOrderLine.getActualTotalReplyAmount();
            if (actualTotalReplyAmount > totalScItemAmount) {
                forecastOrderLine.setActualTotalReplyAmount(actualTotalReplyAmount - totalScItemAmount);
                forecastOrderLine.setStatus(ForecastStatusEnum.PARTIAL_REPLY.getNumValue());
            } else {
                forecastOrderLine.setActualTotalReplyAmount(0);
                forecastOrderLine.setStatus(ForecastStatusEnum.WAITING_FOR_REPLY.getNumValue());
            }
            forecastOrderLines.add(forecastOrderLine);
        });
        if (CollectionUtils.isEmpty(forecastOrderLines)) {
            return Result.success(null);
        }
        ForecastOrderSDO detail = forecastOrderQueryRepository.queyrDetail(tradeMessageSDO.getOrderSDO().getFrontOrderId());
        // 更新主单、子单状态
        forecastOrderWriteRepository.updateForecastStatus(forecastOrderLines, detail);
        return Result.success(null);
    }

    public int totalScItemAmount(List<OrderLineSDO> orderLineList) {
        int totalAmount = 0;
        for (OrderLineSDO sdo : orderLineList) {
            Integer integer = Optional.ofNullable(sdo.getScItemSDO()).map(com.epoch.app.otsb2btradecenter.sdo.ScItemSDO::getQuantity).orElse(0);
            totalAmount = totalAmount + integer;
        }
        return totalAmount;
    }

    /**
     * 获取 登录人 所属销售组织code
     *
     * @param type
     * @return
     */
    private List<OrganizationSDO> getLoginOrganizationCode(Integer type) {
        GetLoginEmployOrganizationPermissionsRequest request = GetLoginEmployOrganizationPermissionsRequest.builder().type(type).build();
        Result<List<OrganizationSDO>> loginEmployOrganizationPermissions = otsPlatformEnhanceService.getLoginEmployOrganizationPermissions(request);
        if (ObjectUtils.isEmpty(loginEmployOrganizationPermissions)) {
            return new ArrayList<>();
        }
        List<OrganizationSDO> result = loginEmployOrganizationPermissions.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return new ArrayList<>();
        }
        return result;
    }

    //补货订单查询活动信息
    private Map<String, List<ActivityInfoResponse>> activityQueryCode(List<ForecastOrderExportRequest> forecastOrderExportRequests) {
        if (CollectionUtils.isEmpty(forecastOrderExportRequests)) {
            return new HashMap<>();
        }
        // 只能根据逐个货品进行活动查询，多个货品的查询结果，无法匹配对应的货品 使用在进行补货活动，其他货品查询活动咨询峥嵘
        Map<String, List<ActivityInfoResponse>> stringListMap = new HashMap<>();
        QueryActivityRequest queryActivityRequest = new QueryActivityRequest();
        List<ActivityInfoRequest> activityInfoRequestList = Lists.newArrayList();
        for (ForecastOrderExportRequest forecastOrder : forecastOrderExportRequests) {
            Date customerExpectTDate = forecastOrder.getCustomerExpectTDate();
            //默认当天
            if (Objects.isNull(customerExpectTDate) || Objects.equals(customerExpectTDate, "")) {
                customerExpectTDate = new Date();
            }
            String s = UUIDUtil.newWithoutMinus();

            CustomerAddressRequest request = new CustomerAddressRequest();
            request.setAddressCode(forecastOrder.getReceiveAddressCode());
            Result<CustomerAddressSDO> customerAddressSDOResult = customerAddressQueryService.queryCustomerAddressByShipAddressId(request);
            String clientId = "";
            if (customerAddressSDOResult.isSuccess() && Objects.nonNull(customerAddressSDOResult.getResult())) {
                clientId = customerAddressSDOResult.getResult().getCustomerCode();
            }

            String key = forecastOrder.getCustomerReferenceNo() + forecastOrder.getScItemId();
            ActivityInfoRequest build = ActivityInfoRequest.builder()
                    //获取客户ID
                    .clientId(clientId) //客户编码
                    .activityUseTime(customerExpectTDate)
                    .deliveryDate(customerExpectTDate)
                    .mainOrderId(key)
                    .subOrderId("subOrder_" + s)
                    .salesOrganization(forecastOrder.getOrganizationCode())
                    .businessChannel(forecastOrder.getChannelCode())
                    .shipAddressId(forecastOrder.getReceiveAddressCode()) //收货地址
                    .orderType(forecastOrder.getOrderType()).build();
            List<ActivityItemInfoRequest> itemList = Lists.newArrayList();
            ActivityItemInfoRequest activityItemInfoRequest = ActivityItemInfoRequest
                    .builder().itemId(forecastOrder.getScItemId())
                    .salesUnit(forecastOrder.getSaleUnit())
                    .itemQuantity(new BigDecimal(forecastOrder.getQuantity()).longValue()).build();
            itemList.add(activityItemInfoRequest);
            build.setItemList(itemList);
            activityInfoRequestList.add(build);
        }
        queryActivityRequest.setActivityInfoRequestList(activityInfoRequestList);
        Result<ActivityResponse> activityResponseResult = activityQueryService.batchQueryCanUsingActivity(queryActivityRequest);
        stringListMap = Nullable.stream(activityResponseResult.getResult().getActivityInfoResponseList()).collect(Collectors.groupingBy(ActivityInfoResponse::getMainOrderId));
        return stringListMap;
    }
}
